描述
在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。
输入
在每组测试数据中。第1行是正整数n,表示有n堆石子。第2 行有n个数,分别表示每堆石子的个数。
输出
程序运行结束时,将计算结果输出。第1 行中的数是最小得分;第2 行中的数是最大得分。
样例输入
4
4 4 5 9
4 4 5 9
样例输出
43
54
54
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <limits.h>
using namespace std;
int dpx[1100][110],p[1100][1100],s[1100],dp[1100][1100];
int anx,any;
int main()
{
int n;
while(cin>>n)
{
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[n+i]=s[i];
}
for(int i=1;i<=2*n;i++)
{
p[i][i]=s[i];
for(int j=i+1;j<=2*n;j++)
p[i][j]=p[i][j-1]+s[j];
}
memset(dp,0,sizeof(dp));
for(int r=1;r<n;r++)
{
for(int i=1;i<=2*n-r;i++)
{
int j=r+i;
dpx[i][j]=INT_MAX;
for(int k=i;k<j;k++)
{
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+p[i][j]);
dpx[i][j]=min(dpx[i][j],dpx[i][k]+dpx[k+1][j]+p[i][j]);
}
}
}
anx=0;
any=INT_MAX;
for(int i=1;i<=n;i++)
{
anx=max(anx,dp[i][n+i-1]);
any=min(any,dpx[i][n+i-1]);
}
printf("%d\n",any);
printf("%d\n",anx);
}
return 0;
}