CDQZ_Training 2012-05-24 笨笨当粉刷匠
题目:
http://cdqz.openjudge.cn/noip/1010/
- 时间限制:
- 10000ms
- 内存限制:
- 128000kB
- 描述
-
笨笨太好玩了,农田荒芜了,彩奖用光了,笨笨只好到处找丁作,笨笨找到了一份粉刷匠的工作。笨笨有n条木板需要被粉刷。每条木板被分成m个格子,每个格子要被刷成红色或蓝色。笨笨每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色,已知每个格子最多只能被粉刷一次。
如果笨笨只能粉刷t次,他最多能正确粉刷多少格子。
一个格子如果未被粉刷或被粉刷成错误颜色,就算粉刷错误。 - 输入
- 第一行三个数n,m,t;
接下来n行,每行一个长度为m的字符“O”表示红色,“l”表示蓝色。 - 输出
- 一个整数,最多能正确粉刷的格子数。
- 样例输入
- 3 6 3
- 111111
- 000000
- 001100
- 样例输出
- 16
题解:
这是SCOI2009的题,又被改过来了………………关键数据都一样……………………
DP,对每行分开操作,用f[i][j][0/1/2]表示该行前i个格子刷j次且第i格子为某种颜色(0/1,2代表不涂),转移比较简单。在做出每行的之后,再用背包对所有行做一次DP即可。
View Code
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5
6 using namespace std;
7
8 int f[55][55][2510][2],g[55][2510],n,m,t,h[55][2510];
9
10 char map[60][60];
11
12 int main()
13 {
14
15 scanf("%d%d%d",&n,&m,&t);
16 for (int a=1;a<=n;a++)
17 scanf("%s",map[a]+1);
18 for (int a=1;a<=n;a++)
19 for (int b=1;b<=m;b++)
20 map[a][b]-='0';
21 memset(f,-1,sizeof(f));
22 memset(g,-1,sizeof(g));
23 memset(h,-1,sizeof(h));
24 for (int a=1;a<=n;a++)
25 {
26 f[a][1][0][0]=f[a][1][0][1]=0;
27 f[a][1][1][map[a][1]]=1;
28 f[a][1][1][1-map[a][1]]=0;
29 g[a][0]=0;
30 g[a][1]=1;
31 for (int b=2;b<=m;b++)
32 {
33 f[a][b][0][0]=f[a][b][0][1]=0;
34 for (int c=1;c<=t;c++)
35 {
36 if (f[a][b-1][c][map[a][b]]!=-1) f[a][b][c][map[a][b]]=max(f[a][b][c][map[a][b]],f[a][b-1][c][map[a][b]]+1);
37 if (c!=0 && f[a][b-1][c-1][0]!=-1) f[a][b][c][map[a][b]]=max(f[a][b][c][map[a][b]],f[a][b-1][c-1][0]+1);
38 if (c!=0 && f[a][b-1][c-1][1]!=-1) f[a][b][c][map[a][b]]=max(f[a][b][c][map[a][b]],f[a][b-1][c-1][1]+1);
39 if (f[a][b-1][c][1-map[a][b]]!=-1) f[a][b][c][1-map[a][b]]=max(f[a][b][c][1-map[a][b]],f[a][b-1][c][1-map[a][b]]);
40 if (c!=0 && f[a][b-1][c-1][0]!=-1) f[a][b][c][1-map[a][b]]=max(f[a][b][c][1-map[a][b]],f[a][b-1][c-1][0]);
41 if (c!=0 && f[a][b-1][c-1][1]!=-1) f[a][b][c][1-map[a][b]]=max(f[a][b][c][1-map[a][b]],f[a][b-1][c-1][1]);
42 g[a][c]=max(f[a][b][c][1],max(g[a][c],f[a][b][c][0]));
43 }
44 }
45 }
46 h[0][t]=0;
47 int ans=-1;
48 for (int a=1;a<=n;a++)
49 for (int b=0;b<=t;b++)
50 for (int c=b;c<=t;c++)
51 if (h[a-1][c]!=-1)
52 {
53 h[a][c-b]=max(h[a][c-b],h[a-1][c]+g[a][b]);
54 ans=max(h[a][c-b],ans);
55 }
56 printf("%d\n",ans);
57
58 return 0;
59 }