HRBUST 1819
石子合并问题--圆形版 | ||||||
|
||||||
Description | ||||||
在圆形操场上摆放着一行共n堆的石子。现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请编辑计算出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。 | ||||||
Input | ||||||
输入有多组测试数据。
每组第一行为n(n<=100),表示有n堆石子,。 二行为n个用空格隔开的整数,依次表示这n堆石子的石子数量ai(0<ai<=100) |
||||||
Output | ||||||
每组测试数据输出有一行。输出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。 中间用空格分开。 | ||||||
Sample Input | ||||||
3
1 2 3 |
||||||
Sample Output | ||||||
9 11 |
代码:
//前一个题的变形,直线变环,把石子接成2*n堆,再进行dp就行了,始终控制区间的最大长度是n。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int inf=0x3f3f3f3f; int n,a[210],dp1[210][210],dp2[210][210],sum[210]; int main() { while(scanf("%d",&n)==1){ sum[0]=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); a[n+i]=a[i]; } memset(dp1,inf,sizeof(dp1)); memset(dp2,0,sizeof(dp2)); for(int i=1;i<=2*n;i++){ sum[i]=sum[i-1]+a[i]; dp1[i][i]=dp2[i][i]=0; } for(int i=2;i<=2*n;i++){ for(int j=i-1;j>=(i<=n?1:i-n+1);j--){ for(int k=j;k<i;k++){ dp1[j][i]=min(dp1[j][i],dp1[j][k]+dp1[k+1][i]+sum[i]-sum[j-1]); dp2[j][i]=max(dp2[j][i],dp2[j][k]+dp2[k+1][i]+sum[i]-sum[j-1]); } } } int ans1=inf,ans2=0; for(int i=1;i<=n;i++){ ans1=min(ans1,dp1[i][i+n-1]); ans2=max(ans2,dp2[i][i+n-1]); } printf("%d %d\n",ans1,ans2); } return 0; }