BZOJ1296 [SCOI2009] 粉刷匠 【dp】

BZOJ1296  [SCOI2009] 粉刷匠

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=1~n,首先第一次先把第 i 行的前 j 个格涂 k 次的 dp 求出来,然后第二次再把前 i 行涂 j 次的 dp 求出来,最后 max(dp[n][i]) 就是最终答案。

代码:

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,t,ans;
 4 int sum[55];
 5 int f[55][55],dp[55][2505];
 6 char s[60];
 7 int main()
 8 {
 9     scanf("%d%d%d",&n,&m,&t);
10     for (int i=1; i<=n; i++)
11     {
12         scanf("%s",s+1);
13         for (int j=1; j<=m; j++)
14           sum[j]=sum[j-1]+(s[j]=='1');
15         for (int j=1; j<=m; j++)
16           for (int x=1; x<=m; x++)
17           {
18               f[x][j]=0;
19               for (int y=0; y<x; y++)
20               {
21                 int tmp=sum[x]-sum[y];
22               f[x][j]=max(f[x][j],f[y][j-1]+max(tmp,x-y-tmp)); 
23             }
24           }
25         for (int j=1; j<=t; j++)
26         {
27             int tmp=min(m,j);
28             for (int k=1; k<=tmp; k++)
29               dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]);
30         }
31     }
32     for (int i=1; i<=t; i++)
33       ans=max(dp[n][i],ans);
34     cout<<ans<<endl;
35     return 0;
36 }
View Code

 

 

 

加油加油加油!!! fighting fighting fighting !!!

 

posted on 2018-06-28 19:41  Frank-King  阅读(114)  评论(0编辑  收藏  举报