洛谷P4158 [SCOI2009]粉刷匠

传送门

设$dp[i][j][k][0/1]$表示在涂点$(i,j)$,涂了$k$次,当前点的颜色是否对,最多能刷对多少个格子

首先换行的时候肯定得多刷一次

然后是如果和前一个格子颜色相同,那么当前点是否刷对都要转移

如果和前一个格子颜色不相同,那么就考虑是否要再刷一次还是直接转移

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std;
 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 6 char buf[1<<21],*p1=buf,*p2=buf;
 7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
 8 int read(){
 9     #define num ch-'0'
10     char ch;bool flag=0;int res;
11     while(!isdigit(ch=getc()))
12     (ch=='-')&&(flag=true);
13     for(res=num;isdigit(ch=getc());res=res*10+num);
14     (flag)&&(res=-res);
15     #undef num
16     return res;
17 }
18 const int N=55;
19 int n,m,t,dp[N][N][N*N][2],col[N][N],ans;
20 int main(){
21 //    freopen("testdata.in","r",stdin);
22     n=read(),m=read(),t=read();
23     for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){
24         char ch;while((ch=getc())!='0'&&ch!='1');
25         col[i][j]=ch-'0';
26     }
27     for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int k=1;k<=t;++k){
28         if(j==1){
29             dp[i][j][k][0]=max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1]);
30             dp[i][j][k][1]=max(dp[i-1][m][k-1][1],dp[i-1][m][k-1][0])+1;
31         }else{
32             if(col[i][j]==col[i][j-1]){
33                 dp[i][j][k][1]=dp[i][j-1][k][1]+1;
34                 dp[i][j][k][0]=dp[i][j-1][k][0];
35             }else{
36                 dp[i][j][k][1]=max(dp[i][j-1][k-1][1]+1,dp[i][j-1][k][0]+1);
37                 dp[i][j][k][0]=max(dp[i][j-1][k][1],dp[i][j-1][k-1][0]);
38             }
39         }cmax(ans,max(dp[i][j][k][0],dp[i][j][k][1]));
40     }
41     printf("%d\n",ans);
42     return 0;
43 }

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/9826660.html
今日推荐