题目链接:http://poj.org/problem?id=3253
题目大意:
有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度
给定各个要求的小木板的长度,及小木板的个数n,求最小费用
以
3
5 8 5为例:
先从无限长的木板上锯下长度为 21 的木板,花费 21
再从长度为21的木板上锯下长度为5的木板,花费5
再从长度为16的木板上锯下长度为8的木板,花费8
总花费 = 21+5+8 =34
解题思路:哈夫曼编码模板
代码:
使用数组的普通方法:
1 #include<iostream> 2 #include<queue> 3 #include<vector> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 //输入 8 int n,a[20005]; 9 10 //使用数组维护最大最小值(每次维护复杂度O(n)) 11 void solve1(){ 12 ll ans=0; 13 14 while(n>1){ 15 int mi1=0,mi2=1;//mi1最小值的下标,mi2次小值的下标 16 if(a[mi1]>a[mi2]) swap(mi1,mi2); 17 for(int i=2;i<n;i++){ 18 if(a[mi1]>a[i]){ 19 mi2=mi1; 20 mi1=i; 21 } 22 else if(a[mi2]>a[i]){ 23 mi2=i; 24 } 25 } 26 int t=a[mi1]+a[mi2]; 27 ans+=t; 28 if(mi1==n-1) swap(mi1,mi2); 29 a[mi1]=t; 30 a[mi2]=a[n-1]; 31 n--; 32 } 33 cout<<ans<<endl; 34 } 35 int main(){ 36 cin>>n; 37 for(int i=0;i<n;i++){ 38 cin>>a[i]; 39 } 40 solve1(); 41 return 0; 42 }
使用STL优先队列:
1 #include<iostream> 2 #include<queue> 3 #include<vector> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 //输入 8 int n,a[20005]; 9 //优先队列维护最小与次小值(初始化复杂度O(n),每次维护复杂度O(log2n)) 10 void solve2(){ 11 priority_queue<ll,vector<ll>,greater<ll> >q; 12 ll ans=0; 13 for(int i=0;i<n;i++){ 14 q.push(a[i]); 15 } 16 while(q.size()>1){ 17 ll mi1=q.top();//最小 18 q.pop(); 19 ll mi2=q.top();//次小 20 q.pop(); 21 q.push(mi1+mi2);//合并 22 ans+=mi1+mi2; 23 } 24 cout<<ans<<endl; 25 } 26 int main(){ 27 cin>>n; 28 for(int i=0;i<n;i++){ 29 cin>>a[i]; 30 } 31 solve2(); 32 return 0; 33 }