地址 http://poj.org/problem?id=3253
题解
本题是<挑战程序设计>一书的例题
根据树中描述 所有切割的代价 可以形成一颗二叉树
而最后的代价总和是与子节点和深度相关的 由于切割的次数是确定的 该二叉树的节点就是确定的。
也就是说我们可以贪心的处理 最小长度的子节点放在最下面
如图
ac代码如下 使用了堆 记录每次最小的元素
堆的使用真的不是很方便 , 另外还需要注意 爆int 所以需要使用long long 记录元素的和
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 #include <assert.h> 5 6 7 8 using namespace std; 9 10 /* 11 poj 3253 12 有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度 13 给定各个要求的小木板的长度,及小木板的个数n,求最小费用 14 提示: 15 以 16 3 17 8 8 5为例: 18 19 先从无限长的木板上锯下长度为 21 的木板,花费 21 20 再从长度为21的木板上锯下长度为5的木板,花费5 21 再从长度为16的木板上锯下长度为8的木板,花费8 22 总花费 = 21 + 5 + 8 = 34 23 */ 24 25 26 int main() 27 { 28 int n; long long ret = 0; 29 cin >> n; 30 vector<int> wood(n); 31 for (int i = 0; i < n; i++) { 32 cin >> wood[i]; 33 } 34 make_heap(wood.begin(), wood.end(), greater<int>()); 35 36 while (wood.size() != 1) { 37 38 pop_heap(wood.begin(), wood.end(), greater<int>()); 39 long long total = wood.back(); 40 wood.pop_back(); 41 42 pop_heap(wood.begin(), wood.end(), greater<int>()); 43 total += wood.back(); 44 wood.pop_back(); 45 46 ret += total; 47 wood.push_back(total); 48 push_heap(wood.begin(), wood.end(), greater<int>()); 49 } 50 51 cout << ret << endl; 52 53 return 0; 54 }
1 #include <iostream> 2 #include <queue> 3 4 #include <stdio.h> 5 6 7 using namespace std; 8 9 typedef long long LL; 10 11 const int MAX_N = 100010; 12 int n, L[MAX_N]; 13 14 void solve() 15 { 16 LL ans = 0; 17 priority_queue<int, vector<int>, greater<int>> que; 18 for (int i = 0; i < n; i++) { 19 que.push(L[i]); 20 } 21 22 while (que.size() > 1) { 23 int l1, l2; 24 l1 = que.top(); 25 que.pop(); 26 l2 = que.top(); 27 que.pop(); 28 29 ans += l1 + l2; 30 que.push(l1 + l2); 31 } 32 printf("%lld ", ans); 33 } 34 35 36 int main() 37 { 38 scanf("%d", &n); 39 40 for (int i = 0; i < n; i++) { 41 scanf("%d", &L[i]); 42 } 43 44 solve(); 45 }