在乙個圓形操場的四周擺放n堆石子(n≤500),現要將石子有次序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。
編一程式,由檔案讀入堆數n及每堆的石子數;
⑴ 選擇一種合併石子的方案,使得做n-1次合併,得分的總和最小;
⑵ 選擇一種合併石子的方案,使得做n-1次合併,得分的總和最大。
輸入檔案:
第1行為n,代表n堆石子;
第2行為n個數,代表每堆石子的數量。
輸出檔案:
第1行為合併的得分總和最小值;
第2行為合併的得分總和最大值。
輸入樣例:
4
4 5 9 4(從最上面的一堆數起,順時針數)
輸出樣例:
43(最小)
54(最大)
【分析】
6堆石子合併的最小得分方案min是由merge(①,②,③)+merge(④,⑤,⑥)得來的,上述中,merge表示合併。merge(①,②,③)時,它有兩種合併方案,即先merge(①,②)兩堆,再將①②合併的結果與第③堆合併,或先merge(②,③),再將②③合併的結果與第①堆合併。兩種方案的合併過程如下:
第一種合併方案:(3+4)+6合併得分為7+13=20;
第二種合併方案:3+(4+6)合併得分為10+13=23。
兩種方案相比,明顯第一種方案得分小。merge(④,⑤,⑥)時,同樣的,也有兩種方案,即先merge④,⑤兩堆,再將④⑤合併的結果與第⑥堆合併,或merge⑤,⑥,再將⑤⑥合併的結果與第④堆合併。兩種方案的合併過程如下:
第一種合併方案:(5+4)+2合併得分為9+11=20;
第二種合併方案:5+(4+2)合併得分為6+11=17。
這兩種方案相比,明顯第二種方案得分小。從圖2-2中的最小合併得分結果來看,在計算6堆石子合併的最小得分min時,它的計算過程明顯是取min和min的。由此可以初步看出,合併石子時具備最優子結構的性質。詳細看合併1到6堆時存在的過程。
合併1堆:①,②,…,⑥;
合併2堆:①②,②③,…,⑥①;
合併3堆:①②③,②③④,…,⑥①②;
合併4堆:①②③④,②③④⑤,…,⑥①②③;
合併5堆:①②③④⑤,②③④⑤⑥,…,⑥①②③④;
合併6堆:①②③④⑤⑥,②③④⑤⑥①,…,⑥①②③④⑤。
有合併過程可以看出,從第i堆開始合併j堆時,它的值可以為第i堆+min。如從第①堆開始合併4堆時,它可以為第①堆+min,可以為min+min,可以為min+第④堆,共有3種**,與區間的合併有關。以此類推,合併到6堆時,取從第i堆開始合併6堆的最小值,即得到合併的總的最小值。所以,我們可以肯定地說,此問題具備最優子結構的性質,而且無後效性。
用合併的堆數作階段,用f[i,j]作狀態,表示從第i堆數起,順時針合併j堆的總得分最小值,它包括合併前j-1堆的最小總得分加上這次合併的得分,用sum[i,j]表示這次合併的得分。合併時的堆數可以表示為序列。序列總得來的方案有很多種,我們用子串行1和子串行2表示,如子串行1為,則子串行2為。子串行1和子串行2相鄰,所以,假如子串行1為k堆,則子串行2為j-k堆。由此,可以得到動規方程:
f[i,j]=min
用stone[i]表示初始時每堆的石子數,則動規的初始條件為:
f[i,1]=0
動規的邊界為1≤i<n,1≤j≤n。求最大得分與最小得分方法一樣,只是在計算時反一下即可。本演算法的時間效率為o(n
3)。
#include#include#include#define inf 65535
using namespace std;
int n;
int num[510];///每堆石頭數
int sum[510][510];
int fmin[510][510];///儲存最小
int fmax[510][510];///儲存最大
int main()
///預設好從第i 堆開始合併j堆石頭的當次得分
for(int j=2;j<=n;j++)
}///以合併的堆數為階段,做動態規劃
for(int j=2;j<=n;j++)///階段,即合併堆數}}
///依次判斷石頭的合併位置,求出最小,最大得分
int maxn=0;
int mint=inf;
for(int j=1;j<=n;j++)
printf("%d ",mint);
printf("%d",maxn);
return 0;
}
區間動規經典題 石子合併
在乙個園形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分 試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分 資料的第1行試正整數n,1 n 100,表示有n堆石子.第2行有n個數,分別表示每堆石...
區間動規經典題 石子合併
在乙個園形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分 試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分 資料的第1行試正整數n,1 n 100,表示有n堆石子.第2行有n個數,分別表示每堆石...
動規之 環形石子合併
題目描述 在乙個圓形操場的四周擺放 n 堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。試設計出乙個演算法,計算出將 n 堆石子合併成 1 堆的最小得分和最大得分。輸入格式 資料的第 1 行是正整數 n,表示有 n 堆石子。第 ...