[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; }