http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1117
跟挑战程序书上例题一样,将要切割的n断木板,分别对应二叉树树的叶子节点,则切割的总开销为木板的长度×节点的深度,可以画图理解,那么最短的木板(L1)应当是深度最大的叶子节点之一,次短的板(L2)和它是兄弟节点,由一块长度是(L1+L2) 的木板切割而来,这样可以变成(n-1)块木板,然后递归求解到n==1。
书上贪心部分用的是O(n×n) 的算法 在这里会超时,需要2.4节优先队列O(NlogN)的算法。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 #include <map> 15 #include <queue> 16 17 #define CL(arr, val) memset(arr, val, sizeof(arr)) 18 19 #define ll long long 20 #define inf 0x7f7f7f7f 21 #define lc l,m,rt<<1 22 #define rc m + 1,r,rt<<1|1 23 #define pi acos(-1.0) 24 25 #define L(x) (x) << 1 26 #define R(x) (x) << 1 | 1 27 #define MID(l, r) (l + r) >> 1 28 #define Min(x, y) (x) < (y) ? (x) : (y) 29 #define Max(x, y) (x) < (y) ? (y) : (x) 30 #define E(x) (1 << (x)) 31 #define iabs(x) (x) < 0 ? -(x) : (x) 32 #define OUT(x) printf("%I64d\n", x) 33 #define lowbit(x) (x)&(-x) 34 #define Read() freopen("a.txt", "r", stdin) 35 #define Write() freopen("b.txt", "w", stdout); 36 #define maxn 1000000000 37 #define N 50005 38 using namespace std; 39 40 int L[N]; 41 int main() 42 { 43 // Read(); 44 int n; 45 long long ans=0; 46 scanf("%d",&n); 47 for(int i=0;i<n;i++) scanf("%d",&L[i]); 48 while(n>1) 49 { 50 int m1=0,m2=1; 51 if(L[m1]>L[m2]) swap(m1,m2); 52 for(int i=2;i<n;i++) 53 { 54 if(L[m1]>L[i]) 55 { 56 m2=m1; 57 m1=i; 58 } 59 else if(L[m2]>L[i]) 60 { 61 m2=i; 62 } 63 } 64 //printf("%d %d\n",L[m1],L[m2]); 65 int t=L[m1]+L[m2]; 66 ans+=t; 67 if(m1==n-1) swap(m1,m2); 68 L[m1]=t; 69 L[m2]=L[n-1]; 70 n--; 71 } 72 printf("%lld\n",ans); 73 return 0; 74 }
优化后的代码:每次只需要选择长度最小的两块木板,则用优先队列从小到大排序,每次把取出来的两块木板之和压进队列即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 //#include <map> 15 #include <queue> 16 17 #define CL(arr, val) memset(arr, val, sizeof(arr)) 18 19 #define ll long long 20 #define inf 0x7f7f7f7f 21 #define lc l,m,rt<<1 22 #define rc m + 1,r,rt<<1|1 23 #define pi acos(-1.0) 24 25 #define L(x) (x) << 1 26 #define R(x) (x) << 1 | 1 27 #define MID(l, r) (l + r) >> 1 28 #define Min(x, y) (x) < (y) ? (x) : (y) 29 #define Max(x, y) (x) < (y) ? (y) : (x) 30 #define E(x) (1 << (x)) 31 #define iabs(x) (x) < 0 ? -(x) : (x) 32 #define OUT(x) printf("%I64d\n", x) 33 #define lowbit(x) (x)&(-x) 34 #define Read() freopen("a.txt", "r", stdin) 35 #define Write() freopen("b.txt", "w", stdout); 36 #define maxn 1000000000 37 #define N 50005 38 using namespace std; 39 40 int L[N]; 41 priority_queue<int, vector<int>, greater<int> >que; 42 int main() 43 { 44 //Read(); 45 int n; 46 scanf("%d",&n); 47 for(int i=0;i<n;i++) 48 { 49 scanf("%d",&L[i]); 50 que.push(L[i]); 51 } 52 ll ans=0; 53 while(que.size()>1) 54 { 55 int l1,l2; 56 l1=que.top(); 57 que.pop(); 58 l2=que.top(); 59 que.pop(); 60 ans+=l1+l2; 61 que.push(l1+l2); 62 } 63 printf("%lld\n",ans); 64 return 0; 65 }
时间: 2024-10-01 03:52:14