1. 程式人生 > >洛谷P4158 [SCOI2009]粉刷匠

洛谷P4158 [SCOI2009]粉刷匠

() fin != fine sdi %d bsp https 如果

傳送門

設$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 }

洛谷P4158 [SCOI2009]粉刷匠