區間DP:石子歸併

題目描述 
Description

有n堆石子排成一列,每堆石子有一個重量w[i], 每次合併能夠合併相鄰的兩堆石子,一次合併的代價爲兩堆石子的重量和w[i]+w[i+1]。問安排怎樣的合併順序,可以使得總合並代價達到最小。spa

輸入描述  Input Description

第一行一個整數n(n<=100)ip

第二行n個整數w1,w2...wn  (wi <= 100)it

輸出描述  Output Description

一個整數表示最小合併代價io

樣例輸入  Sample Input

4class

4 1 1 4變量

樣例輸出 
Sample Output
18

這道題能夠輕鬆地找出狀態轉移方程f[i,j]:=max{f[i,k]+f[k+1,j]}+sum[i,j];

但問題是如何遞推是個問題,
1:若正推,for i:=1 to n do
for j:=i to n do
這樣的話,遞推順序爲(1,1),(1,2),(1,3),(1,4),(2,2).....
中間還有未求的量。
2:若逆推,順序爲(n,n),(n-1,n-1),(n-1,n),(n-2,n-2)....。故應逆推。

還有一點要注意,就是當前所求的區間的前趨i,後趨j,和中間變量k有(i=j-1=k)時f[i,j]:=stone[i]+stone[j];

var num:longint;
stone:array[1..100]of integer;
i,j,k,l,n,max:longint;
sum:array[1..100,1..100]of longint;
f:array[1..100,1..100]of longint;
 
  
begin fillchar(stone,sizeof(stone),0);
fillchar(sum,sizeof(sum),0);
fillchar(f,sizeof(f),$7F);
readln(n);
for i:=1 to n do
read(stone[i]);
for i:=1 to n do
for j:=i to n do
for k:=i to j do
sum[i,j]:=sum[i,j]+stone[k];
for i:=1 to n do
f[i,i]:=0;
for i:=n downto 1 do
for j:=i to n do
for k:=i to j-1 do
if (i=k)and(k=j-1)
then begin if f[i,j]>f[i,k]+f[k+1,j]+sum[i,j]
then f[i,j]:=stone[i]+stone[j];
end
else begin if f[i,j]>f[i,k]+f[k+1,j]+sum[i,j]
then f[i,j]:=f[i,k]+f[k+1,j]+sum[i,j];
end;
writeln(f[1,n]);
end.
相關文章
相關標籤/搜索