nyoj 737 石子合併(一) 區間動規
阿新 • • 發佈:2019-02-08
- 描述
- 有N堆石子排成一排,每堆石子有一定的數量。現要將N堆石子併成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過N-1次合併後成為一堆。求出總的代價最小值。
- 輸入
- 有多組測試資料,輸入到檔案結束。
每組測試資料第一行有一個整數n,表示有n堆石子。
接下來的一行有n(0< n <200)個數,分別表示這n堆石子的數目,用空格隔開 - 輸出
- 輸出總代價的最小值,佔單獨的一行
- 樣例輸入
-
3 1 2 3 7 13 7 8 16 21 4 18
- 樣例輸出
-
9 239
- 來源
- 經典問題
- 上傳者
- TC_胡仁東
ps: 區間dp。。。本題需要寫兩個狀態,,分別是每一個區間的和,也是上一局的總花費精力。。另一個需要的就是dp狀態轉移方程。。
這一局需要三層for迴圈。。第三層的作用是分割區間。
例如:1 2 3 4 可以分為:
1 234
12 34
123 4
本題i依然為區間長度,j為起始區間
程式碼如下:
#include<stdio.h> #include<string.h> const int inf=1000000; int d[220][220],w[220][220]; int a[220]; int minn(int a,int b) { return a<b?a:b; } int main() { int n; while(~scanf("%d",&n)) { memset(d,inf,sizeof(d)); memset(w,0,sizeof(w)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); w[1][i]=a[i]; d[1][i]=0; } for(int i=2;i<=n;i++) { for(int j=1;j<=n;j++) { w[i][j]=w[i-1][j]+w[1][i+j-1]; //printf("##%d\n",w[i][j]); } } for(int i=2;i<=n;i++) { for(int j=1;j<=n-i+1;j++) { for(int k=1;k<i;k++) { d[i][j]=minn(d[k][j]+d[i-k][k+j],d[i][j]); } d[i][j]+=w[i][j]; //printf("###%d %d\n",d[i][j],w[i][j]); } } printf("%d\n",d[n][1]); } }