[NOI1995]石子合并

考试的原题,我居然对了.....因为是一个环,所以你要算一个两遍.....你就要从前往后算一遍,再从后向前算一遍.....

方程:

dp1[i][j]=min(dp1[i][k]+dp1[k+1][j]+ans[j]-ans[i-1],dp1[i][j]);
dp2[i][j]=max(dp2[i][k]+dp2[k+1][j]+ans[j]-ans[i-1],dp2[i][j]);

代码:

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(isdigit(ch)==0 && ch!='-')ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void write(int x)
{
    int f=0;char ch[20];
    if(!x){puts("0");return;}
    if(x<0){putchar('-');x=-x;}
    while(x)ch[++f]=x%10+'0',x/=10;
    while(f)putchar(ch[f--]);
    putchar('
');
}
int dp1[1100][1100];
int dp2[1100][1100];
int n,m;
int a[110000];
int ans[11000];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];//输入 
		a[i+n]=a[i];//倒着存一遍 
	}
	for(int i=1;i<=2*n;i++)//前缀和 
	{
		ans[i]=ans[i-1]+a[i];
	}
	for(int i=(n*2)-1;i>=1;i--)//找 
	{
		for(int j=i+1;j<=i+n;j++)//赋初值 
		{
			dp1[i][j]=2147483647;
			dp2[i][j]=0;
			for(int k=i;k<j;k++)
			{
				dp1[i][j]=min(dp1[i][k]+dp1[k+1][j]+ans[j]-ans[i-1],dp1[i][j]);
				dp2[i][j]=max(dp2[i][k]+dp2[k+1][j]+ans[j]-ans[i-1],dp2[i][j]);
			}
		}
	}
	int sum1=9999999,sum2=0;
	for(int i=1;i<=n;i++)
	{
		sum1=min(sum1,dp1[i][i+n-1]);//依次比较 
		sum2=max(sum2,dp2[i][i+n-1]);
	}
	cout<<sum1<<endl;
	cout<<sum2<<endl;
}

  

原文地址:https://www.cnblogs.com/dai-jia-ye/p/9378064.html