石子合併(一) 區間dp
阿新 • • 發佈:2019-01-31
石子合併(一)
題目描述:
有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
程式碼:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define inf 0x3f3f3f #define N 205 #define mem(a,b) memset(a,b,sizeof(a)) int a[N],sum[N],d[N][N]; int main() { int n; while(~scanf("%d",&n)) { mem(a,0); mem(sum,0); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; //sum[i]記錄前i個石子的總代價 } for(int l=1;l<=n;l++) for(int i=1;i+l<=n;i++) //d[i][j]記錄合併i到j區間的石子所需最小代價 { int j=i+l; d[i][j]=inf; for(int k=i;k<=j;k++) d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]+sum[j]-sum[i-1]); } printf("%d\n",d[1][n]); } return 0; }