CSU - 1592 石子归并
现在有n堆石子,第i堆有ai个石子。现在要把这些石子合并成一堆,每次只能合并相邻两个,每次合并的代价是两堆石子的总石子数。求合并所有石子的最小代价。
Input
第一行包含一个整数T(T<=50),表示数据组数。
每组数据第一行包含一个整数n(2<=n<=100),表示石子的堆数。
第二行包含n个正整数ai(ai<=100),表示每堆石子的石子数。
Output
每组数据仅一行,表示最小合并代价。
Sample Input
2 4 1 2 3 4 5 3 5 2 1 4
Sample Output
19 33
Hint
用区间DP的lik通式做。
转移方程:dp【i】【j】=min(dp【i】【j】,dp【i】【k】+dp【k+1】【j】+c)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 6 using namespace std; 7 8 int a[105],b[105][105],c[105]; 9 10 int dfs(int i,int j) 11 { 12 if(b[i][j]!=-1) 13 return b[i][j]; 14 int t=1e9; 15 for(int k=i;k<j;k++) 16 { 17 t=min(t,dfs(i,k)+dfs(k+1,j)+c[j]-c[i-1]); 18 //cout<<i<< " "<<j<<" "<<t<<endl; 19 } 20 // b[i][j]=t; 21 return b[i][j]=t; 22 } 23 24 int main() 25 { 26 int T; 27 scanf("%d",&T); 28 while(T--) 29 { 30 int n; 31 scanf("%d",&n); 32 for(int i=0;i<n;i++) 33 for(int j=0;j<n;j++) 34 b[i][j]=-1; 35 for(int i=0;i<n;i++) 36 { 37 scanf("%d",&a[i]); 38 c[i]=a[i]+c[i-1]; 39 //cout<<c[i]<<endl; 40 b[i][i]=0; 41 } 42 int s=dfs(0,n-1); 43 printf("%d\n",s); 44 } 45 46 47 48 return 0; 49 }