1. 程式人生 > 其它 >石子合併——區間dp

石子合併——區間dp

282. 石子合併 - AcWing題庫

 

所有的區間dp問題列舉時,第一維通常是列舉區間長度,並且一般 len = 1 時用來初始化,列舉從 len = 2 開始;第二維列舉起點 i (右端點 j 自動獲得,j = i + len - 1)

這就是典型的區間dp問題。因為求的是1到n的代價最小值,所以我們可以先一般化,最後再得出特殊的1到n的代價。

狀態表示:區間【i,j】的代價總和的最小值。

 

對於區間【i,j】,我們可以細化分為【i,k】與【k+1,j】的合併項,其中k的範圍是大於等於i,小於j。

狀態計算:
1.如果i==j,則f [ i , j ] 初始化為0

2.如果i!= j,則f [ i , j ] = min( f [ i ] [ k ] + f [k  +1  ][ j  ] + s[ j ] - s [ i  -1 ] )

  其中s[ j ] - s [ i  -1 ]是從i到j的代價字首和相減得到的最後一次兩堆石子合併的代價和

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=350;
 4 int a[N],f[N][N],s[N];
 5 
 6 int main()
 7 {
 8     int n;scanf("%d",&n);
 9     for(int i=1;i<=n;i++)
10     {
11         scanf("%d",&a[i]);
12         s[i]=s[i-1
]+a[i]; 13 } 14 15 for(int len=1;len<=n;len++) 16 { 17 for(int i=1;i+len-1<=n;i++) 18 { 19 int j=i+len-1; 20 if(i==j) //初始化 21 { 22 f[i][j]=0; 23 continue; 24 } 25 f[i][j]=0x3f3f3f3f
; //初始化 26 for(int k=i;k<j;k++) 27 { 28 f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]); 29 } 30 } 31 } 32 33 printf("%d\n",f[1][n]); 34 35 return 0; 36 }
View Code