动态规划 BZOJ1296 [SCOI2009]粉刷匠
1296: [SCOI2009]粉刷匠
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1993 Solved: 1149
[Submit][Status][Discuss]
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 。
Source
先每个木板分开暴力地计算刷t/m次最多能刷对的数量,再进行汇总地动归
正解很容易想到
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,t,ans; 7 char s[60]; 8 int sum[60],f[60][60],g[60][2510]; 9 int main(){ 10 scanf("%d%d%d",&n,&m,&t); 11 for(int i=1;i<=n;i++){ 12 scanf("%s",s+1); 13 for(int j=1;j<=m;j++) sum[j]=sum[j-1]+(s[j]=='1'); 14 for(int k=1;k<=m;k++) 15 for(int j=1;j<=m;j++){ 16 f[j][k]=0; 17 for(int p=0;p<=j-1;p++) f[j][k]=max(f[j][k],f[p][k-1]+max(sum[j]-sum[p],j-p-sum[j]+sum[p])); 18 } 19 for(int j=1;j<=t;j++) 20 for(int k=1;k<=min(j,m);k++) g[i][j]=max(g[i][j],g[i-1][j-k]+f[m][k]); 21 } 22 for(int i=1;i<=t;i++) ans=max(ans,g[n][i]); 23 printf("%d\n",ans); 24 return 0; 25 }