洛谷 P4158 [SCOI2009]粉刷匠 题解
每日一题 day59 打卡
Analysis
很容易看出是一个dp,
dp[i][j[k][0/1]来表示到了(i,j)时,刷了k次,0表示这个没刷,1表示刷了。
于是有转移:
1.换行时一定要重新刷
2.若这一格与前一个格子颜色一样,最优的方式是把前一个的1状态原封不动转移,这时的0状态也跟着原封不动算一个贪心:
dp[i][j][k][1]=dp[i][j-1][k][1]+1;
dp[i][j][k][0]=dp[i][j-1][k][0];
3.否则1就有两个选择: (不要忘记我们设的1状态是强制这一格有贡献) 一个是牺牲一次k换种颜色刷,另一个是继续上一格的颜色
dp[i][j][k][1]=max(dp[i][j-1][k-1][1]+1,dp[i][j-1][k][0]+1);
4.0也要贪心,因为这一格跟上一个不一样,所以如果要继续刷错,可能是从上一次1原封不动过来,可能是再用一刷使得刷错.
dp[i][j][k][0]=max(dp[i][j-1][k][1],dp[i][j-1][k-1][0]);
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define int long long 7 #define rep(i,s,e) for(register int i=s;i<=e;++i) 8 #define dwn(i,s,e) for(register int i=s;i>=e;--i) 9 using namespace std; 10 inline int read() 11 { 12 int x=0,f=1; 13 char c=getchar(); 14 while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} 15 while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();} 16 return f*x; 17 } 18 inline void write(int x) 19 { 20 if(x<0) {putchar('-'); x=-x;} 21 if(x>9) write(x/10); 22 putchar(x%10+'0'); 23 } 24 int n,m,t,ans; 25 int map[51][51]; 26 int dp[51][51][2501][2]; 27 signed main() 28 { 29 n=read();m=read();t=read(); 30 rep(i,1,n) 31 rep(j,1,m) 32 { 33 char c=getchar(); 34 while(c!='0'&&c!='1') c=getchar(); 35 map[i][j]=c-'0'; 36 } 37 rep(i,1,n) 38 rep(j,1,m) 39 rep(k,1,t) 40 { 41 if(j==1) 42 { 43 dp[i][j][k][0]=max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1]); 44 dp[i][j][k][1]=max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1])+1; 45 } 46 else 47 { 48 if(map[i][j]==map[i][j-1]) 49 { 50 dp[i][j][k][1]=dp[i][j-1][k][1]+1; 51 dp[i][j][k][0]=dp[i][j-1][k][0]; 52 } 53 else 54 { 55 dp[i][j][k][0]=max(dp[i][j-1][k-1][0],dp[i][j-1][k][1]); 56 dp[i][j][k][1]=max(dp[i][j-1][k-1][1],dp[i][j-1][k][0])+1; 57 } 58 } 59 ans=max(ans,max(dp[i][j][k][0],dp[i][j][k][1])); 60 } 61 write(ans); 62 return 0; 63 }
请各位大佬斧正(反正我不认识斧正是什么意思)