WELCOME

任何一个伟大的目标,都有一个微不足道的开始。

【一本通提高区间类动态规划】石子合并

【一本通提高区间类动态规划】石子合并


目录

【一本通提高区间类动态规划】石子合并

原题

题目描述

输入格式

输出格式

输入输出样例

AC代码


原题

题目描述

在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

试设计出一个算法,计算出将N堆石子合并成1堆的最小得分和最大得分。

输入格式

数据的第1行是正整数N,表示有N堆石子。

第2行有N个整数,第 i 个整数 a_{i} 表示第 i 堆石子的个数。

输出格式

输出共2行,第1行为最小得分,第2行为最大得分。

输入输出样例

输入

4

4 5 9 4

输出

43

54

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,a[210],f[210][210],f2[210][210],sum[210][210],ans1=2147483600,ans2=-2147483600;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		a[i+n]=a[i];
	}
	for(int i=1;i<=n*2;i++)
	{
		for(int j=1;j<=n*2;j++)
		{
			for(int k=i;k<=j;k++)
			{
				sum[i][j]+=a[k];
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		f[i][i]=f2[i][i]=0;
	}
	for(int l=1;l<n;l++)
	{
		for(int i=1,j=i+l;i<n*2&&j<n*2;i++,j=i+l)
		{
			f[i][j]=2147483600;
			for(int k=i;k<j;k++)
			{
				f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[i][j]);
				f2[i][j]=max(f2[i][j],f2[i][k]+f2[k+1][j]+sum[i][j]);
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		ans1=min(ans1,f[i][i+n-1]);
		ans2=max(ans2,f2[i][i+n-1]);
	}
	cout<<ans1<<endl<<ans2;
	return 0;
}

求点赞!! 

posted @ 2021-04-03 09:13  绿树公司  阅读(44)  评论(0)    收藏  举报