洛谷P1880 [NOI1995]石子合并 题解

版权声明:点个赞再走呗,转载请注明出处 https://blog.csdn.net/qq_41431457/article/details/89415999

题目描述

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

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

输入输出格式

输入格式:

数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

输出格式:

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

输入输出样例

输入样例#1: 复制

4
4 5 9 4

输出样例#1: 复制

43
54

一道区间dp题,第一次写区间dp,真尼玛玄学

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int a[205],sum[205];
int opt1[205][205],opt2[205][205];
int sun(int i,int j)//求出区间[i,j]的和 
{
	return sum[j]-sum[i-1];
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		a[n+i]=a[i];//变成环状 
	}
	
	for(int i=1;i<=2*n;i++)//方便求区间和
	sum[i]=sum[i-1]+a[i]; 
	
	for(int l=1;l<n;l++)//枚举区间长度 
	for(int i=1,j=i+l;i<2*n&&j<2*n;i++,j=i+l)//枚举各个长度为l的区间 
	{
		opt2[i][j]=inf;
		
		for(int k=i;k<j;k++)//区间上求最优解 
		{
			opt1[i][j]=max(opt1[i][j],opt1[i][k]+opt1[k+1][j]+sun(i,j));
			opt2[i][j]=min(opt2[i][j],opt2[i][k]+opt2[k+1][j]+sun(i,j));
		}
	}
	
	int min_ans=inf, max_ans=0;
	for(int i=1;i<=n;i++)//找到长度为n的最优区间 取其值 
	{
		max_ans=max(max_ans,opt1[i][i+n-1]);
		min_ans=min(min_ans,opt2[i][i+n-1]);
	}
	
	cout<<min_ans<<endl<<max_ans;
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41431457/article/details/89415999