题目描述
有N堆石子排成一排(n<=100),现要将石子有次序地合并成一堆,规定每次只能选相邻的两堆合并成一堆,并将新的一堆的石子数,记为改次合并的得分,编一程序,由文件读入堆数n及每堆石子数(<=200);
(1)选择一种合并石子的方案,使得做n-1次合并,得分的总和最少
(2)选择一种合并石子的方案,使得做n-1次合并,得分的总和最多
输入
第一行为石子堆数n
第二行为每堆石子数,每两个数之间用一空格分隔。
第二行为每堆石子数,每两个数之间用一空格分隔。
输出
从第1至第n行为得分最小合并方案,第n+1行为空行,从n+2到2n+1行是得分最大的合并方案。
样例输入
44 5 9 4
样例输出
4454
#include <bits/stdc++.h>
using namespace std;
int dp1[110][110],a[110],sum[110];
int dp2[110][110];
int main()
{
int n;
while(~scanf("%d",&n)){
int i,j,k;
for(i=1; i<=n; i++)
scanf("%d",&a[i]),sum[i]=a[i]+sum[i-1];
for(i=1; i<=n; i++)
for(j=i; j<=n; j++){
dp1[i][j]=i==j?0:99999;
dp2[i][j]=0;
}
for(i=1; i<n; i++)
for(j=1; j<=n-i; j++)
for(k=j; k<=i+j-1; k++){
dp1[j][i+j]=min(dp1[j][i+j],dp1[j][k]+dp1[k+1][i+j]+sum[i+j]-sum[j-1]);
dp2[j][i+j]=max(dp2[j][i+j],dp2[j][k]+dp2[k+1][i+j]+sum[i+j]-sum[j-1]);
}
printf("%d\n%d\n",dp1[1][n],dp2[1][n]);
}
return 0;
}