本蒟蒻的思路是dp[x][i][j][k][0/1]表示在第x个木板,区间[i,j]粉刷k次且最开始把区间刷成0/1的最多的收益,因为刷总比不刷优秀,枚举i,j,k,中间点mid,那么可以从dp[x][i][mid][k-1/k][0/1],dp[x][mid+1][j][k-1/k][0/1]转移,具体代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=51;
int dp[N][N][N][N][2],dp1[N][N*N];
int c[N][N*N];
int a[N][N],sum[N][N][2];
int n,m,T;
int q(int x,int l,int r,int op){
return sum[x][r][op]-sum[x][l-1][op];
}
signed main(){
cin>>n>>m>>T;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
char ch;
cin>>ch;
sum[i][j][0]=sum[i][j-1][0],sum[i][j][1]=sum[i][j-1][1];
a[i][j]=(ch=='1'),sum[i][j][a[i][j]]++;
}
for(int x=1;x<=n;x++){
for(int i=1;i<=m;i++)dp[x][i][i][1][a[x][i]]=1;
for(int len=2;len<=m;len++){
for(int i=1;i+len-1<=m;i++){
int j=i+len-1;
for(int k=1;k<=len;k++){
dp[x][i][j][k][0]=dp[x][i][j][k-1][0];
dp[x][i][j][k][1]=dp[x][i][j][k-1][1];
for(int mid=i;mid<j;mid++){
dp[x][i][j][k][0]=max(dp[x][i][mid][k][0]+q(x,mid+1,j,0),dp[x][i][j][k][0]);
dp[x][i][j][k][0]=max(dp[x][mid+1][j][k][0]+q(x,i,mid,0),dp[x][i][j][k][0]);
dp[x][i][j][k][0]=max(dp[x][i][mid][k-1][1]+q(x,mid+1,j,0),dp[x][i][j][k][0]);
dp[x][i][j][k][0]=max(dp[x][mid+1][j][k-1][1]+q(x,i,mid,0),dp[x][i][j][k][0]);
dp[x][i][j][k][1]=max(dp[x][i][mid][k][1]+q(x,mid+1,j,1),dp[x][i][j][k][1]);
dp[x][i][j][k][1]=max(dp[x][mid+1][j][k][1]+q(x,i,mid,1),dp[x][i][j][k][1]);
dp[x][i][j][k][1]=max(dp[x][i][mid][k-1][0]+q(x,mid+1,j,1),dp[x][i][j][k][1]);
dp[x][i][j][k][1]=max(dp[x][mid+1][j][k-1][0]+q(x,i,mid,1),dp[x][i][j][k][1]);
}
}
}
}
for(int i=1;i<=m;i++)c[x][i]=max({c[x][i-1],dp[x][1][m][i][0],dp[x][1][m][i][1]});
}
int lim=0;
for(int i=1;i<=n;i++){
lim+=m,lim=min(lim,T);
for(int j=1;j<=lim;j++){
dp1[i][j]=dp1[i-1][j];
for(int k=0;k<=min(j,m);k++)
dp1[i][j]=max(dp1[i-1][j-k]+c[i][k],dp1[i][j]);
}
}
if(T>n*m)cout<<n*m;
else cout<<dp1[n][T];
return 0;
}