POJ 3253 Fence Repair(哈夫曼编码)

题目链接: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 } 

 

posted @ 2017-06-07 17:25  Yeader  阅读(223)  评论(0编辑  收藏  举报