BZOJ1084_最大子矩阵_KEY
DP。
但要分类讨论,对于M=1和M=2的情况分别讨论。
1>M=1
设f[i][j]表示选了i个矩阵,到第j位。N^3转移。(前缀和)
2>M=2
设f[i][j][k]表示选了i个矩阵,第一列到i,第二列到j。
枚举i,j,k后枚举j1和k1表示选一行的情况。
如果j==k则可以从之前的两行一起转移。
code:
/************************************************************** Problem: 1084 User: yekehe Language: C++ Result: Accepted Time:112 ms Memory:1476 kb ****************************************************************/ #include <cstdio> #include <algorithm> using namespace std; int f[15][105][105]; int N,M,K,a[105][3],sum[105][3]; int F[15][105]; int S[105]; void work() { for(int i=1;i<=N;i++){scanf("%d",&S[i]);S[i]+=S[i-1];} for(int i=1;i<=K;i++)for(int j=1;j<=N;j++)F[i][j]=-1e9; for(int i=1;i<=K;i++) for(int j=1;j<=N;j++){ F[i][j]=F[i][j-1]; for(int k=0;k<j;k++){ F[i][j]=max(F[i][j],F[i-1][k]+S[j]-S[k]); } } printf("%d",F[K][N]); return ; } int main() { scanf("%d%d%d",&N,&M,&K); if(M==1)return work(),0; for(int i=1;i<=N;i++) for(int j=1;j<=M;j++){ scanf("%d",&a[i][j]); sum[i][j]=sum[i-1][j]+a[i][j]; } for(int i=1;i<=K;i++)for(int j=1;j<=N;j++)for(int k=1;k<=N;k++)f[i][j][k]=-1e9; for(int i=1;i<=K;i++) for(int j=1;j<=N;j++) for(int k=1;k<=N;k++){ f[i][j][k]=max(f[i][j-1][k],f[i][j][k-1]); for(int j1=0;j1<j;j1++) f[i][j][k]=max(f[i][j][k],f[i-1][j1][k]+sum[j][1]-sum[j1][1]); for(int k1=0;k1<k;k1++) f[i][j][k]=max(f[i][j][k],f[i-1][j][k1]+sum[k][2]-sum[k1][2]); if(j==k) for(int h=0;h<j;h++) f[i][j][k]=max(f[i][j][k],f[i-1][h][h]+sum[j][1]-sum[h][1]+sum[k][2]-sum[h][2]); } printf("%d",f[K][N][N]); return 0; }