[区间DP][SCOI2009]粉刷匠

题目描述

windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。

windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。

如果windy只能粉刷 T 次,他最多能正确粉刷多少格子?

一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。

输入格式

第一行包含三个整数,N M T。

接下来有N行,每行一个长度为M的字符串,'0'表示红色,'1'表示蓝色。

输出格式

包含一个整数,最多能正确粉刷的格子数。

输入输出样例

输入
3 6 3
111111
000000
001100
输出
16

说明/提示

30%的数据,满足 1 <= N,M <= 10 ; 0 <= T <= 100 。

100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500 。

题解

f[i][j][k][0/1]为刷到第i行第j个 刷了k次 错误粉刷 或刷对 的刷对的格子数

最后这一维转移的讨论避免枚举断点,优化时间复杂度

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int n,m,t;
 5 char a[52][52]; int f[52][52][2505][2];
 6 int main()
 7  {        
 8  scanf("%d%d%d",&n,&m,&t); 
 9  for(int i=1;i<=n;i++)    {scanf("%s",a[i]+1);}    
10  int ans=0;
11  for(int i=1;i<=n;i++)
12   for(int j=1;j<=m;j++)
13       for(int k=1;k<=t;k++)
14        {if(j==1) 
15          {f[i][j][k][0]=max(f[i-1][m][k-1][0],f[i-1][m][k-1][1]);
16           f[i][j][k][1]=f[i][j][k][0]+1;                  
17          }
18         else if(a[i][j]==a[i][j-1])
19              {f[i][j][k][0]=f[i][j-1][k][0];
20               f[i][j][k][1]=f[i][j-1][k][1]+1;
21              }
22         else {f[i][j][k][0]=max(f[i][j-1][k][1],f[i][j-1][k-1][0]);
23                 f[i][j][k][1]=max(f[i][j-1][k-1][1]+1,f[i][j-1][k][0]+1);
24              }   
25         ans=max(ans,max(f[i][j][k][0],f[i][j][k][1]));     
26      }
27  printf("%d",ans);    
28 return 0;
29  }

 

posted @ 2019-11-13 22:09  YuXiaoze  阅读(153)  评论(0编辑  收藏  举报