对于每一个m的dp没有什么难的,总的背包dp也不难,但是两个连在一块真是非常巧妙
整体来看,就是,将t次的粉刷次数分给各个行求的最大值。就是分配
先预处理(dp)每一行粉刷1~min(t,m)(因为一行最多涂m次,所以处理到m就可以了)次的最大粉刷格子数。发现很像泛化背包的模型,再外层再做一次分组背包就可以了
这所以这么做是因为:我们可以发现不同的木板是相互独立,怎么计算和处理之间互相无影响的,影响的只是在不同木板上分配的粉刷次数
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
char s[55];
int f[55][55][55],n,m,t;
int dp[2650],sum[55];
bool b[2650];
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++) sum[j]=sum[j-1]+s[j]-'0';
for (int j=1;j<=min(t,m);j++)
for (int l=1;l<=m;l++)
{
f[i][j][l]=f[i][j-1][l];
f[i][j][l]=max(f[i][j][l],f[i][j][l-1]);
for (int k=0;k<l;k++)
f[i][j][l]=
max(f[i][j][l],f[i][j-1][k]+max(sum[l]-sum[k],l-k-sum[l]+sum[k]));
}
}
b[0]=true;
for (int i=1;i<=n;i++)
{
for (int j=t;j>=0;j--)
if (b[j])
{
for (int l=1;l<=min(t,m);l++)
{
dp[j+l]=max(dp[j+l],dp[j]+f[i][l][m]);
b[j+l]=true;
}
}
}
int ans=0;
for (int i=1;i<=t;i++) ans=max(ans,dp[i]);
printf("%d",ans);
return 0;
}