bzoj 1084
由于m只会是1或者2,那么就干脆分类讨论,可以开两个namespace实现。
当m为1时。
设dp[i][j]表示前i个数中选了j个矩阵的最大值。
dp[i][j]=max(dp[i-1][j],dp[k][j-1]+sum[i]-sum[k])(0<=k<i)。
当m为2时。
设dp[i][j][k]表示第一列前i个,第2列前j个中选了k个矩阵的最大值。
dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k])
dp[i][j][k]=max(dp[h][j][k-1]+sum[i][0]-sum[h][0],dp[i][j][k])(0<=h<i)
dp[i][j][k]=max(dp[i][h][k-1]+sum[j][1]-sum[h][1],dp[i][j][k])(0<=h<j)
dp[i][j][k]=max(dp[h][h][k-1]+sum[i][0]-sum[h][0]+sum[j][1]-sum[h][1],dp[i][j][k])(i=j,0<=h<i)]
貌似忘记赋值为-oo还是过了。
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; #define k1 sum[i][0]-sum[h][0] #define k2 sum[j][1]-sum[h][1] int read(){ char c; while(!isdigit(c=getchar()) && c!='-'); int x=0,y=1; if(c=='-') y=-1; else x=c-'0'; while(isdigit(c=getchar())) x=x*10+c-'0'; return x*y; } namespace f1{ int dp[101][11],sum[101]; void work(int n,int c){ for(int i=1;i<=n;i+=1) sum[i]=sum[i-1]+read(); for(int i=1;i<=n;i+=1) for(int k=1;k<=c;k+=1) dp[i][k]=-2e9; for(int i=1;i<=n;i+=1) for(int j=1;j<=c;j+=1){ dp[i][j]=dp[i-1][j]; for(int k=i-1;k>=0;k-=1) dp[i][j]=max(dp[k][j-1]+sum[i]-sum[k],dp[i][j]); } printf("%d",dp[n][c]); } }; namespace f2{ int dp[101][101][11],sum[101][2]; void work(int n,int c){ for(int i=1;i<=n;i+=1) for(int j=0;j<2;j+=1) sum[i][j]=sum[i-1][j]+read(); for(int i=0;i<=n;i+=1) for(int j=0;j<=n;j+=1) for(int k=1;k<=c;k+=1) dp[i][j][k]=-2e9; for(int i=1;i<=n;i+=1) for(int j=1;j<=n;j+=1) for(int k=1;k<=c;k+=1){ dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k]); for(int h=0;h<i;h+=1) dp[i][j][k]=max(dp[h][j][k-1]+k1,dp[i][j][k]); for(int h=0;h<j;h+=1) dp[i][j][k]=max(dp[i][h][k-1]+k2,dp[i][j][k]); if(i==j) for(int h=0;h<i;h+=1) dp[i][j][k]=max(dp[h][h][k-1]+k1+k2,dp[i][j][k]); } printf("%d",dp[n][n][c]); } }; int main(){ int n=read(),m=read(),c=read(); if(m==1) f1::work(n,c); else f2::work(n,c); return 0; }