石子合併(區間DP)

2022-09-22 04:21:09 字數 2144 閱讀 3750

設有 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的乙個最小值

#includeusing

namespace

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 個數,分別表示...