本文地址:http://www.javashuo.com/article/p-mlslnsqi-gc.htmlhtml
題目名稱:Fence Repairide
連接:http://poj.org/problem?id=3253spa
題意:農夫準備把木板切成n塊,每塊長度爲Li,每次切木板時須要花費切時木板的長度的開銷(好比把21切成13和8,開銷就是切以前的長度12)。計算把木板切完的最小開銷。3d
思路:直接拿刀去切木板貌似沒有什麼貪心的思路呀。可是咱們把切的過程畫成樹的樣子就會發現開銷等於各葉子節點的 木板長度乘以節點深度 的和。反過來想,最短與次短的兩塊應該在最下面且是兄弟節點,就是每次把最小的兩塊合起來,而後依次貪心就能獲得最小值。(也就是哈夫曼樹)
code
代碼以下:htm
一、直接循環查找最小和次小 O(n2)blog
1 #include<cstdio>
2 #include<algorithm>
3 using namespace std; 4 typedef long long ll; 5 int L[20005]; 6 int main(){ 7 int n; 8 scanf("%d",&n); 9 for(int i = 0; i < n; i++) 10 scanf("%d", &L[i]); 11 ll sum = 0; 12 while(n > 1){ 13 int min1 = 0, min2 = 1; //最小和次小
14 if(L[min1] > L[min2]) 15 swap(min1, min2); 16 for(int i = 2; i < n; i++){ 17 if(L[i] < L[min1]){ 18 min2 = min1; 19 min1 = i; 20 } 21 else if(L[i] < L[min2]) 22 min2 = i; 23 } 24 int t = L[min1] + L[min2]; 25 sum += t; 26 if(min1 == n-1) swap(min1,min2); 27 L[min1] = t; 28 L[min2] = L[n-1]; 29 n--; 30 } 31 printf("%lld\n",sum); 32 return 0; 33 }
二、用優先隊列 O(nlogn)隊列
1 #include<cstdio>
2 #include<queue>
3 #include<algorithm>
4 using namespace std; 5 typedef long long LL; 6 int main() { 7 int n; 8 scanf("%d", &n); 9 priority_queue<int, vector<int>,greater<int> > que; 10 int s; 11 for(int i = 0; i < n; i++) { 12 scanf("%d", &s); 13 que.push(s); 14 } 15 LL ans = 0; 16 while(que.size() > 1) { 17 int s1,s2; 18 s1 = que.top(); 19 que.pop(); 20 s2 = que.top(); 21 que.pop(); 22 ans += s1 + s2; 23 que.push(s1 + s2); 24 } 25 printf("%lld\n", ans); 26 return 0; 27 }