BZOJ_1296_[SCOI2009]粉刷匠_DP
BZOJ_1296_[SCOI2009]粉刷匠_DP
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。
设h[i][j]表示前i个位置涂了j次。
然后放在一起,用每行使用涂的次数来转移。
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; int h[55][55],g[55][55],f[55][2550],n,m,K,s1[55],s2[55]; char s[55]; int main() { scanf("%d%d%d",&n,&m,&K); int i,j,k,l; for(i=1;i<=n;i++) { scanf("%s",s+1); for(j=1;j<=m;j++) s1[j]=s1[j-1]+(s[j]=='1'),s2[j]=s2[j-1]+(s[j]=='0'); memset(h,0,sizeof(h)); for(j=1;j<=m;j++) { for(k=1;k<=j;k++) { h[j][k]=h[j-1][k]; for(l=0;l<j;l++) { h[j][k]=max(h[j][k],h[l][k-1]+max(s1[j]-s1[l],s2[j]-s2[l])); } } } for(j=1;j<=m;j++) g[i][j]=h[m][j]; } int ans=0; for(i=1;i<=n;i++) { for(j=0;j<=K;j++) { for(k=0;k<=j;k++) { f[i][j]=max(f[i][j],f[i-1][k]+g[i][j-k]); } ans=max(ans,f[i][j]); } } printf("%d\n",ans); }