题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1296
对于不同木板之间,最终统计答案时做一个分组背包即可;
而要进行分组背包,就需要知道每个木板被刷几次的最大正确格子数;
所以对于每个木板分别DP,状态 f[i][j] 定义为前 i 个格子刷 j 次的最大正确格子数;
转移时枚举断点,从那以后刷一个颜色,带上新加入的这个点,就可以进行DP了。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,t,f[55][2505],s1[55],s0[55],ans,dp[55][2505]; int main() { scanf("%d%d%d",&n,&m,&t); for(int i=1;i<=n;i++) { memset(f,0,sizeof f); memset(s1,0,sizeof s1); memset(s0,0,sizeof s0); for(int j=1,x;j<=m;j++) { scanf("%1d",&x); s1[j]=s1[j-1];s0[j]=s0[j-1]; if(x)s1[j]++; else s0[j]++; for(int k=1;k<=min(j,t);k++)//次数 for(int l=0;l<j;l++)//断点 f[j][k]=max(f[j][k],f[l][k-1]+max(s1[j]-s1[l],s0[j]-s0[l])); } for(int j=1;j<=t;j++)//次数 for(int k=0;k<=j&&k<=m;k++)//给i的次数 dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]); } for(int i=1;i<=t;i++)ans=max(ans,dp[n][i]); printf("%d",ans); return 0; }