DP
我连背包都不会了
做两遍DP,第一遍求出每一行刷 k k k次分别最多能刷对多少个格子。第二遍就把第一遍的当作分组背包来选物品就好了。
设 f [ i ] [ j ] f[i][j] f[i][j]表示当前这行做到第 i i i列,刷了 j j j次的最多格子数。那么有 f [ i ] [ j ] = m a x { f [ k ] [ j − 1 ] + m a x { s 0 i − s 0 k , s 1 i − s 1 k } } f[i][j]=max\{f[k][j-1]+max\{s0_i-s0_k,s1_i-s1_k\}\} f[i][j]=max{f[k][j−1]+max{s0i−s0k,s1i−s1k}}。其中 s 0 , s 1 s0,s1 s0,s1分别为 0 0 0和 1 1 1的前缀和。
分组背包就不用说了吧。。。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 55
using namespace std;
int n,m,t,ans,s0[N],s1[N],f[N][N],g[N][N*N];
char s[N];
int main(){
scanf("%d%d%d",&n,&m,&t);
for (int i=1;i<=n;i++){
scanf("%s",s+1);
for (int j=1;j<=m;j++){
s0[j]=s0[j-1],s1[j]=s1[j-1];
s[j]=='0'?s0[j]++:s1[j]++;
for (int k=0;k<=m;k++) f[j][k]=0;
}
for (int j=1;j<=m;j++)
for (int p=1;p<=j;p++)
for (int k=0;k<j;k++)
f[j][p]=max(f[j][p],f[k][p-1]+max(s0[j]-s0[k],s1[j]-s1[k]));
for (int j=1;j<=t;j++)
for (int k=0,p=min(m,j);k<=p;k++)
g[i][j]=max(g[i][j],g[i-1][j-k]+f[m][k]);
}
for (int i=1;i<=t;i++) ans=max(ans,g[n][i]);
return printf("%d",ans),0;
}