設有 n
'>n
n 堆石子排成一排,其編號為 1,2
,3,…
,n'>1,2,3,…,n
1,2,3,…,n。
每堆石子有一定的質量,可以用乙個整數來描述,現在要將這 n
'>n
n 堆石子合併成為一堆。
每次只能合併相鄰的兩堆,合併的代價為這兩堆石子的質量之和,合併後與這兩堆石子相鄰的石子將和新堆相鄰,合併時由於選擇的順序不同,合併的總代價也不相同。
例如有 4
'>4
4 堆石子分別為1 3 5 2
, 我們可以先合併 1、2
'>1、2
1、2 堆,代價為 4
'>4
4,得到4 5 2
, 又合併 1,2
'>1,2
1,2 堆,代價為 9
'>9
9,得到9 2
,再合併得到 11
'>11
11,總代價為 4+9
+11=24
'>4+9+11=24
4+9+11=24;
如果第二步是先合併 2,3
'>2,3
2,3 堆,則代價為 7
'>7
7,得到4 7
,最後一次合併代價為 11
'>11
11,總代價為 4+7
+11=22
'>4+7+11=22
4+7+11=22。
問題是:找出一種合理的方法,使總的代價最小,輸出最小代價。
輸入格式
第一行乙個數 n
'>n
n 表示石子的堆數 n
'>n
n。第二行 n
'>n
n 個數,表示每堆石子的質量(均不超過 1000
'>1000
1000)。
輸出格式
輸出乙個整數,表示最小代價。
資料範圍1≤
n≤300'>1≤n≤300
1≤n≤300
輸入樣例:
輸出樣例:4
1 3 5 2
22
注意題目說是合併相鄰的兩堆,y總說如果不相鄰會變成貪心的問題,類似於合併果子,我沒看見過這題,qaq...
upc好像做過類似的,哦哦哦,想起來了,一直排序的好像用貪心
回歸到這個題目來:
因為是合併相鄰的堆,n個物品,兩兩合併有n-1個選法,合併完再合併有n-2種選法sa...最後合併為一堆的時候有(n-1)!的選法
所以暴力列舉必超時,hhh,想到了用dp來寫
令f[i][j]為區間i~j合併為一堆的最小代價
分析:因為是相鄰的,所以要想合併為一堆,那必定左邊某一段(個)與右邊某一段(個)合併
這題光這麼看這個圖有點抽象,下面來分析一下:
首先令f[i][j]為區間i到j的最小代價
不管怎麼樣,都可以被分為連續的兩堆,左邊一堆的最小代價是f[i,k]右邊的是f[k+1][j]兩個最小代價分別相加是變成這兩隊的總代價,最後這兩堆還要再合併成一堆不要忘了
f[i][j]=f[i][k]+f[k+1][j]+s[j]-s[i-1]
具體的怎麼實現呢
肯定是從小到大的,就是從乙個個的小塊2變成最後的兩堆,既然分析以區間為基準
①列舉區間,從長度為2開始
②算每個區間從i到j的乙個最小代價
③列舉分割點了,把每乙個分割線的值都算出來,最後求總的最小值
這樣操作下來,由此往上推,就是整個區間1到n的乙個最小值
#includeusingnamespace
std;
const
int n=310
;int
f[n][n];
inta[n],s[n];
intmain()
for(int len=2;len<=n;len++)//
列舉區間長度
}cout
<1][n]<
return0;
}
石子合併 (區間DP
問題描述 在乙個操場上擺放著一行共n堆的石子。現要將石子有序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆石子數記為該次合併的得分。請編輯計算出將n堆石子合併成一堆的最小得分和將n堆石子合併成一堆的最大得分。輸入檔案 輸入第一行為n n 1000 表示有n堆石子,第二行為n個用空...
石子合併 區間dp
有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。假設dp 1 4 表示將區間1 4的石子合併所花費的代價。dp 1 4 可以劃分為dp 1 1 dp 2...
石子合併 (區間DP)
題目鏈結 描述 有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入第一行有乙個整數n,表示有n堆石子。接下來的一行有n 0 n 200 個數,分別表示...