题目大意:给定n*m的木板,每个点需要刷成1和0两种颜色之一,每次只能刷一行中连续的一段,一个点只能刷一次,求T刷子最多能刷对多少个点
首先对每行拆开处理 令f[i][j]为用i刷子刷前j个格子最多刷对多少个点 动规处理出这一行刷i刷子最多能刷对多少个点 然后分组背包即可
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 60
using namespace std;
int n,m,T,f[M][M];
//f[i][j]表示用i刷子刷前j个格子能刷出的最多格子
//f[i][j]=max{ f[i-1][k]+max(cnt[0],cnt[1]) }
//(i-1<=k<=j-1)
char s[M];
int a[M][M];
//a[i][j]表示第i行用j刷子能刷出的最大价值
void DP(int pos)
{
int i,j,k;
memset(f,0xef,sizeof f);
f[0][0]=0;
for(i=1;i<=m;i++)
{
for(j=i;j<=m;j++)
{
int cnt[2]={0};
for(k=j-1;k>=i-1;k--)
{
cnt[s[k+1]-'0']++;
f[i][j]=max(f[i][j],f[i-1][k]+max(cnt[0],cnt[1]));
}
}
}
for(i=1;i<=m;i++)
a[pos][i]=f[i][m];
}
int Packet_Backpack()
{
int i,j,k;
static int g[M][M*M];
memset(g,0xef,sizeof g);
g[0][0]=0;
for(i=1;i<=n;i++)
for(j=0;j<=m;j++)
for(k=T;k>=j;k--)
g[i][k]=max(g[i][k],g[i-1][k-j]+a[i][j]);
return g[n][T];
}
int main()
{
int i;
cin>>n>>m>>T;
for(i=1;i<=n;i++)
{
scanf("%s",s+1);
DP(i);
}
cout<<Packet_Backpack()<<endl;
}