【两种方法】基础实验4-2.7 修理牧场 (25 分)
立志用最少的代碼做最高效的表達
農夫要修理牧場的一段柵欄,他測量了柵欄,發現需要N塊木頭,每塊木頭長度為整數L?i個長度單位,于是他購買了一條很長的、能鋸成N塊的木頭,即該木頭的長度是Li的總和。
 
 但是農夫自己沒有鋸子,請人鋸木的酬金跟這段木頭的長度成正比。為簡單起見,不妨就設酬金等于所鋸木頭的長度。例如,要將長度為20的木頭鋸成長度為8、7和5的三段,第一次鋸木頭花費20,將木頭鋸成12和8;第二次鋸木頭花費12,將長度為12的木頭鋸成7和5,總花費為32。如果第一次將木頭鋸成15和5,則第二次鋸木頭花費15,總花費為35(大于32)。
 
 請編寫程序幫助農夫計算將木頭鋸成N塊的最少花費。
輸入格式:
 輸入首先給出正整數N(≤10?^4),表示要將木頭鋸成N塊。第二行給出N個正整數(≤50),表示每段木塊的長度。
輸出格式:
 輸出一個整數,即將木頭鋸成N塊的最少花費。
輸入樣例:
 8
 4 5 1 2 1 3 1 1
 
 輸出樣例:
 49
逆向思考:假設已經有N個鋸開的木塊,粘合兩塊的花費是合并后的長度,要如何粘合才能使花費最小? 這個問題與原問題是等價的, 很容易看出這就是構建哈夫曼樹的過程。
實現要點:算法需要從一個集合中反復取最小值,同時不斷將兩個最小值相加新產生的數據放進集合,于是最小堆稱為最合適的工具。
當然也可以使用封裝好的“最小堆”,也就是優先隊列。
下面分別給出最小堆與優先隊列的實現方法
優先隊列解法
#include<queue> #include<iostream> #include<cstdio> using namespace std; int main() {int n; cin >> n;priority_queue<int, vector<int>, greater<int> >q;for(int i = 0; i < n; i++) {int x; cin >> x; q.push(x);}int n1 = n-1;long long sum = 0;while(n1--) {int x1 = q.top(); q.pop();int x2 = q.top(); q.pop();sum += x1+x2;q.push(x1+x2);}cout << sum << '\n';return 0; }最小堆解法
#include<iostream> #include<cstdio>using namespace std; const int Mindata = 0; const int Maxdata = 500000; const int Scale = 10000;typedef struct node* Heap; int ans = 0; struct node{int* Data;int size;int capacity; //直接定義為無限大 }; Heap creatminheap(int maxsize) {Heap H = new node();H->Data = (int*)malloc(2*(maxsize+1) * sizeof(int)); //???H->size = 0;H->Data[0] = Mindata; return H; }Heap insert(Heap H, int x) {int mom;for(mom=++H->size; x < H->Data[mom/2]; mom /= 2)H->Data[mom] = H->Data[mom/2];H->Data[mom] = x;return H; }int DeleteMin(Heap H) {int Parent, Child;int MinItem, X;MinItem = H->Data[1]; //刪除的是最小的節點 H->Data[1] = H->Data[H->size--]; //x等于小根堆最后一個節點(最大的節點)for(Parent = 1; Parent*2 <= H->size; Parent = Child) {Child = Parent*2;if((Child != H->size) && (H->Data[Child] > H->Data[Child + 1]))Child++; //Child指向左右子節點的較小者if(H->Data[Parent] < H->Data[Child]) //剪枝 break;else swap(H->Data[Parent], H->Data[Child]);}return MinItem; }int main() {int n, tmp;cin >> n;Heap H = creatminheap(n);for(int i = 0; i < n; i++) {cin >> tmp;H = insert(H, tmp);}n--; while(n--) { //砍n-1次 tmp = DeleteMin(H) + DeleteMin(H);ans += tmp;H = insert(H, tmp); }cout << ans; }??????——你的潛意識,正在操控你的人生,而你卻稱之為命運。
總結
以上是生活随笔為你收集整理的【两种方法】基础实验4-2.7 修理牧场 (25 分)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 【详细解析】基础实验4-2.6 目录树
- 下一篇: 【测试点4】基础实验4-2.8 部落 (
