问题描述:
云天明送给程心一串珍贵的项链,上面共有n颗珍珠,每一颗珍珠上都有一个数字。
每两颗相邻的珍珠可以合并为一颗新的珍珠,合并后这两颗珍珠消失,新珍珠上的数字为合并的两颗的的数字之和。并且此次操作的得分要加上这个和。
经过n-1次这样的合并后,项链只剩下最后一颗珍珠,问总得分的最小值和最大值。
编程任务:
对于给定n颗珍珠组成的项链,编程计算合并成一颗珍珠时的最小得分和最大得分。
数据输入:
输入的第 1 行是正整数n,1≤n≤100,表示有 n 颗珍珠。
第二行有n个数,分别表示每颗珍珠上的数字。
结果输出:
输出的第 1 行中的数是最小得分;第 2 行中的数是最大得分。
样例输入:
3
1 2 3
样例输出:
9
11
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=410, INF=0x3f3f3f3f;
int main()
{
int n;
cin >> n;
int a[N]; //记录输入的每串项链珍珠的数量
int sum[N]; //计算前缀和
int Min[N][N]; //表示n颗珍珠合并成一颗珍珠的得分总和最小值
int Max[N][N]; //表示n颗珍珠合并成一颗珍珠的得分总和最大值
memset(Min,INF,sizeof Min); //数组初始化
memset(Max,0,sizeof Max);
for(int i=1;i<=n;i++)
{
cin >> a[i];
a[i+n]=a[i]; //复制一遍区间
}
for(int i=1;i<=2*n;i++)
{
Min[i][i]=0; //初始化
Max[i][i]=0; //初始化
sum[i]=sum[i-1]+a[i]; //计算前缀和
}
for(int len=2;len<=n;len++) //阶段:枚举区间长度,len记录相邻合并的石子数
{
for(int l=1;l+len-1<=2*n;l++) //状态:枚举区间起点
{
int r=l+len-1; //区间终点
for(int k=l; k<r; k++) //决策:枚举分割点
{
Min[l][r]=min(Min[l][r],Min[l][k]+Min[k+1][r]+sum[r]-sum[l-1]);
Max[l][r]=max(Max[l][r],Max[l][k]+Max[k+1][r]+sum[r]-sum[l-1]);
}
}
}
int minn=INF, maxx=0;
for(int i=1;i<=n;i++)
{
minn=min(minn,Min[i][i+n-1]); //Min[1,n],f[2,n+1]..f[n,2n-1]
maxx=max(maxx,Max[i][i+n-1]); //Max[1,n],g[2,n+1]..g[n,2n-1]
}
cout << minn << endl << maxx;
return 0;
}
仅供学习,转发请注明出处!