1296: [SCOI2009]粉刷匠
Submit: 2752 Solved: 1591
[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 。
注意,每个格子只能涂一次
先暴力统计f[k][j],前k个格子涂j次,最多能涂几个
然后背包动规
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 char ch[60]; 7 int n,m,t,ans; 8 int sum[60],f[60][60],g[60][2600]; 9 10 int main() 11 { 12 scanf("%d%d%d",&n,&m,&t); 13 for(int i=1;i<=n;i++) 14 { 15 memset(sum,0,sizeof(sum)); 16 memset(f,0,sizeof(f)); 17 scanf("%s",ch+1); 18 for(int j=1;j<=m;j++) 19 sum[j]=sum[j-1]+(ch[j]=='1'); 20 for(int j=1;j<=m;j++) 21 for(int k=1;k<=m;k++) 22 { 23 for(int l=0;l<k;l++) 24 f[k][j]=max(f[k][j],f[l][j-1]+max(sum[k]-sum[l],(k-l)-(sum[k]-sum[l]))); 25 } 26 for(int j=1;j<=t;j++) 27 for(int k=1;k<=min(j,m);k++) 28 g[i][j]=max(g[i][j],g[i-1][j-k]+f[m][k]); 29 } 30 for(int i=1;i<=t;i++) 31 ans=max(ans,g[n][i]); 32 printf("%d\n",ans); 33 return 0; 34 }