首页 > 代码库 > poj 3253 Fence Repair 优先队列
poj 3253 Fence Repair 优先队列
poj 3253 Fence Repair 优先队列
Description
Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into the N planks (i.e., whose length is the sum of the lengths Li). FJ is ignoring the "kerf", the extra length lost to sawdust when a sawcut is made; you should ignore it, too.
FJ sadly realizes that he doesn‘t own a saw with which to cut the wood, so he mosies over to Farmer Don‘s Farm with this long board and politely asks if he may borrow a saw.
Farmer Don, a closet capitalist, doesn‘t lend FJ a saw but instead offers to charge Farmer John for each of the N-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.
Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create the N planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.
Input
Lines 2.. N+1: Each line contains a single integer describing the length of a needed plank
Output
Sample
Sample Input 3 8 5 8 Sample Output 34
题意:
一块木板,有一定的切割费用,切割费用为木板的长度,比如切割一条长为10的木板,切成4 和 6 费用为10 再讲6切割为3 和 3 切割费用为6,现给定木板的切割的段数以及木板的各段长度,求切割的最小费用。
思路:
首先,切割费用是不同的,比如样例 总长为21,第一次切成16 和 5 第二次将16切成8和8 费用为 21+16=37;如果第一次切成13和8,第二次将13切成8和5,费用为34。看到题之后第一反应是将木板第一次切下最大的,剩余的再切,这样保证结果最小。这样结果是不正确的。正确的是每次选两个最小的木板合成一个较长的木板,再将这些木板合成较大的。用逆推的思想。第一种思路错误是因为第一次切并不一定是自己想要的结果,比如 4 5 6 7 第一次切下7 第二次切下6 第三次切5 最后切下4 这样费用是22+15+9=46。正确做法是4+5=9 6+7=13 9+13=22 这样切费用为22+9+13=44。证明可以用哈弗曼树证明。
代码:
#include<stdio.h> #include<stack> #include<algorithm> #include<queue> #include<iostream> #include<string.h> #include<string> using namespace std; int main() { long long n; while(~scanf("%lld",&n)) { long long sum=0; priority_queue<long long, vector<long long>, greater<long long> > q; for(int i=0; i<n; i++) { long long a; cin>>a; q.push(a); } while(q.size()>1) { long long x,y; x=q.top(); q.pop(); y=q.top(); q.pop(); sum+=(x+y); q.push(x+y); } cout<<sum<<endl; } } /* 4 4 5 6 7 */
poj 3253 Fence Repair 优先队列