(stone.pas/c/cpp)
来源:某年NOI(去巴蜀交)
【问题描述】
在huanxing一个操场上摆放着一行共n堆的石子。现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请编辑计算出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。
【输入文件】
输入第一行为n(n<1000),表示有n堆石子,第二行为n个用空格隔开的整数,依次表示这n堆石子的石子数量(<=1000)
【输出文件】
输出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。
【输入样例】
3
1 2 3
【输出样例】
9 11
#include
#include
#define dmax 9999
int n;
int a[1001];
int dp_max[1001][1001],dp_min[1001][1001];
int sum[1001][1001];
int main()
{
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(dp_max,0,sizeof(dp_max));
memset(sum,0,sizeof(sum));
int i;
int z;
for(i=1;i<=n;i++)
{
for(z=1;z<=n;z++)
{
dp_min[i][z]=dmax;
}
}
for(i=0;i<=n;i++)
dp_min[i][1]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int min=dmax,max=0;
int j,k,t;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i+j-1>n)
{
t=(i+j-1)%n;
for(k=i;k<=n;k++)
{
sum[i][j]+=a[k];
}
for(k=1;k<=t;k++)
{
sum[i][j]+=a[k];
}
}
else
{
t=i+j-1;
for(k=i;k<=t;k++)
{
sum[i][j]+=a[k];
}
}
}
}
for(j=2;j<=n;j++)
{
for(i=1;i<=n;i++)
{
for(k=1;k<=j-1;k++)
{
if(i+k>n)
{
t=(i+k)%n;
}
else
t=i+k;
if(dp_min[i][j]>dp_min[i][k]+dp_min[t][j-k]+sum[i][j])
{
dp_min[i][j]=dp_min[i][k]+dp_min[t][j-k]+sum[i][j];
if(min>dp_min[i][n])
{
min=dp_min[i][n];
}
}
if(dp_max[i][j]