[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('\n');
}
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;
}

浙公网安备 33010602011771号