考虑每行独立计算。
所以可以开一个三维数组: g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k]第 i i i行前 j j j列涂了 k k k次的最大值。
然后再开一个 二维数组 f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i行涂了 j j j次的最大值。
预处理二维前缀和。
然后 g g g 的递推 O ( n m 3 ) O(nm^3) O(nm3) , f f f的递推 O ( n m T ) O(nmT) O(nmT)。
// Problem: P4158 [SCOI2009]粉刷匠
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4158
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-08-24 15:37:22
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=55,M=2505,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
int n,m,T;
char a[N];
int s[N][N],f[N][M];
int g[N][N][N];//第i行前j列涂k次的最大值.
int main(){
scanf("%d%d%d",&n,&m,&T);
for(int i=1;i<=n;i++){
scanf("%s",a+1);
for(int j=1;j<=m;j++)
s[i][j]=s[i][j-1]+(a[j]=='1');
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=m;k++)
for(int x=k-1;x<j;x++){
g[i][j][k]=max(g[i][j][k],g[i][x][k-1]+max(s[i][j]-s[i][x],j-x-s[i][j]+s[i][x]));
}
for(int i=1;i<=n;i++)
for(int j=1;j<=T;j++)
for(int k=0;k<=min(j,m);k++)
f[i][j]=max(f[i][j],f[i-1][j-k]+g[i][m][k]);
int ans=0;
for(int i=1;i<=T;i++)
ans=max(ans,f[n][i]);
printf("%d\n",ans);
return 0;
}