题目描述
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入输出格式
输入格式:
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式:
输出共2行,第1行为最小得分,第2行为最大得分.
输入输出样例
输入样例#1:
4 4 5 9 4
输出样例#1:
43 54
代码:
先拆环为链,再做区间DP。
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 206 4 using namespace std; 5 int n,sum[maxn]; 6 int dpmin[maxn][maxn],dpmax[maxn][maxn]; 7 int main() 8 { 9 scanf("%d",&n); 10 for(int a,i=1;i<=n;i++) 11 { 12 scanf("%d",&a); 13 sum[i]=sum[i-1]+a; 14 sum[i+n]=sum[i]; 15 } 16 for(int i=1;i<n;i++) 17 sum[i+n]+=sum[n]; 18 for(int len=1;len<n;len++) 19 for(int i=1;i<=n*2-1-len;i++) 20 { 21 int j=i+len; 22 int res1=0x7fffffff; 23 int res2=-123456789; 24 for(int k=i;k<j;k++) 25 { 26 res1=min(res1,dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1]); 27 res2=max(res2,dpmax[i][k]+dpmax[k+1][j]+sum[j]-sum[i-1]); 28 } 29 dpmin[i][j]=res1; 30 dpmax[i][j]=res2; 31 } 32 int MIN=0x7fffffff,MAX=0; 33 for(int i=1;i<=n;i++) 34 MIN=min(dpmin[i][i+n-1],MIN),MAX=max(dpmax[i][i+n-1],MAX);//!dp[i][i+n-1] 35 printf("%d %d",MIN,MAX); 36 return 0; 37 }