嗯所以这题利用决策的单调性来减少k断点的枚举次数。具体看lyd书。这部分很生疏,但是我还是选择先不管了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 6 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 7 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 8 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 9 template<typename T>inline T read(T&x){ 10 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 11 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 12 } 13 const int N=200+7,INF=0x3f3f3f3f; 14 int p[N][N],Fmin[N][N],Fmax[N][N],sum[N],a[N]; 15 int n; 16 17 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout); 18 read(n); 19 for(register int i=1;i<=n;++i)a[i+n]=read(a[i]); 20 for(register int i=1;i<(n<<1);++i)sum[i]=sum[i-1]+a[i],p[i][i]=i; 21 for(register int i=(n<<1)-1;i;--i){ 22 for(register int j=i+1;j<(n<<1);++j){ 23 Fmax[i][j]=_max(Fmax[i+1][j],Fmax[i][j-1])+sum[j]-sum[i-1];Fmin[i][j]=INF; 24 for(register int k=p[i][j-1];k<=p[i+1][j];++k) 25 if(MIN(Fmin[i][j],Fmin[i][k]+Fmin[k+1][j]+sum[j]-sum[i-1]))p[i][j]=k; 26 if(!(Fmin[i][j]^INF))Fmin[i][j]=0; 27 } 28 } 29 Fmin[0][0]=INF; 30 for(register int i=1;i<=n;++i)MIN(Fmin[0][0],Fmin[i][i+n-1]),MAX(Fmax[0][0],Fmax[i][i+n-1]); 31 printf("%d %d ",Fmin[0][0],Fmax[0][0]); 32 return 0; 33 }