【算法分析与设计】云天明的项链

问题描述:
云天明送给程心一串珍贵的项链,上面共有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;	
}

仅供学习,转发请注明出处!

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Walker_CodeGou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值