題意:有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n-1次合併後成為一堆。求出總的代價最小值。
解題關鍵:區間dp,首先列舉區間,再列舉分割點,區間由小到大更新。
轉移方程:$dp[l][r] = \min (dp[l][r],dp[l][i + 1] + dp[i + 1][r] + w[i][j])$
複雜度:$o()$
注意$dp[i][i] = 0$
**的比較好的一段理解:
區間動態規劃問題一般都是考慮,對於每段區間,他們的最優值都是由幾段更小區間的最優值得到,是分治思想的一種應用,將乙個區間問題不斷劃分為更小的區間直至乙個元素組成的區間,列舉他們的組合 ,求合併後的最優值。
設f[i,j](1<=i<=j<=n)表示區間[i,j]內的數字相加的最小代價
最小區間f[i,i]=0(乙個數字無法合併,∴代價為0)
每次用變數k(i<=k<=j-1)將區間分為[i,k]和[k+1,j]兩段
for l:=1 to n do // l是區間長度,作為階段。
for i:=1 to n do // i是窮舉的區間的起點
begin
j:=i+l-1; // j是 區間的終點,這樣所有的區間就窮舉完畢
if j>n then break; // 這個if很關鍵。
for k:= i to j-1 do // 狀態轉移,去推出 f[i,j]
f[i , j]= max
end;
這個結構必須記好,這是區間動態規劃的**結構。
1 #include2using
namespace
std;
3 typedef long
long
ll;4
const
int maxn=302;5
inta[maxn],sum[maxn];
6int
dp[maxn][maxn];
7int
main()18}
19 cout<1][n]<<"\n"
;20}21 }
nyoj737 石子合併 區間dp
描述 有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入 有多組測試資料,輸入到檔案結束。每組測試資料第一行有乙個整數n,表示有n堆石子。接下來的一行...
NYOJ 737 石子歸併問題 (區間DP1)
題意 中文題目 解題方法 基礎區間dp。要求n個石子歸併,我們根據dp的思想劃分成子問題,先求出每兩個合併的最小代價,然後每三個的最小代價,依次知道n個。定義狀態dp i j 為從第i個石子到第j個石子的合併最小代價。則有 dp i j m in d p i k dp k 1 j 那麼我們就可以從小...
nyoj 737 石子合併 經典區間 dp
時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入 有多組測試資料,輸入到檔案...