BZOJ系列1296《[SCOI2009]粉刷匠》题解

来源:互联网 发布:淘宝店铺数据统计 编辑:程序博客网 时间:2024/04/29 10:50

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

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;}



0 0
原创粉丝点击