在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
input:
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
output:
输出共2行,第1行为最小得分,第2行为最大得分.
input:
4
4 4 5 9
output:
43
54【参考程序】:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int s1[201][201],f1[201][201];
int s2[201][201],f2[201][201];
int main()
{
int n;
scanf("%d",&n);
int p;
memset(s1,127,sizeof(s1));memset(f1,127,sizeof(f1));
memset(s2,128,sizeof(s2));memset(f2,128,sizeof(f2));
for (int i=1;i<=n;i++)
{
scanf("%d",&p);
s1[i][i]=s2[i][i]=s1[i+n][i+n]=s2[i+n][i+n]=0;
f1[i][i]=f2[i][i]=f1[i+n][i+n]=f2[i+n][i+n]=p;
}
for (int len=2;len<=2*n;len++)
for (int i=1;i<=2*n-len+1;i++)
{
int j=i+len-1;
for (int k=i;k<=j-1;k++)
{
if (f1[i][j]>f1[i][k]+f1[k+1][j])
{
f1[i][j]=f1[i][k]+f1[k+1][j];
s1[i][j]=s1[i][k]+s1[k+1][j]+f1[i][j];
}
else if (f1[i][j]==f1[i][k]+f1[k+1][j])
if (s1[i][j]>s1[i][k]+s1[k+1][j]+f1[i][j])
s1[i][j]=s1[i][k]+s1[k+1][j]+f1[i][j];
if (f2[i][j]<f2[i][k]+f2[k+1][j])
{
f2[i][j]=f2[i][k]+f2[k+1][j];
s2[i][j]=s2[i][k]+s2[k+1][j]+f2[i][j];
}
else if (f2[i][j]==f2[i][k]+f2[k+1][j])
if (s2[i][j]<s2[i][k]+s2[k+1][j]+f2[i][j])
s2[i][j]=s2[i][k]+s2[k+1][j]+f2[i][j];
}
}
int mins=0x7FFFFFFF,maxs=-0x7FFFFFFF;
for (int i=1;i<=n;i++)
{
if (s1[i][i+n-1]<mins) mins=s1[i][i+n-1];
if (s2[i][i+n-1]>maxs) maxs=s2[i][i+n-1];
}
printf("%d\n%d\n",mins,maxs);
return 0;
}