Description
windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。 windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
Input
输入文件paint.in第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,'0'表示红色,'1'表示蓝色。
Output
输出文件paint.out包含一个整数,最多能正确粉刷的格子数。
Sample Input
3 6 3
111111
000000
001100
111111
000000
001100
Sample Output
16
HINT
30%的数据,满足 1 <= N,M <= 10 ; 0 <= T <= 100 。
100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500 。
分析:可以用动态规划来解决。
dp[i][j]表示该行前i个涂j次的最优解。
最后再对于每行做分组背包。
代码如下:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int N,M,T,sum[60],ans;
int t[60][60],f[60][2510];
char s[60];
void init()
{
scanf("%d%d%d",&N,&M,&T);
}
void work()
{
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]=='1');
for(int j=1;j<=M;j++)
for(int x=1;x<=M;x++)
{
t[x][j]=0;
for(int y=0;y<x;y++)
{
int tmp=sum[x]-sum[y];
t[x][j]=max(t[x][j],t[y][j-1]+max(tmp,x-y-tmp));
}
}
for(int j=1;j<=T;j++)
{
int tmp=min(M,j);
for(int k=1;k<=tmp;k++)
f[i][j]=max(f[i][j],f[i-1][j-k]+t[M][k]);
}
}
for(int i=1;i<=T;i++)
ans=max(f[N][i],ans);
printf("%d\n",ans);
}
int main()
{
init();
work();
return 0;
}