題解 P4158 【[SCOI2009]粉刷匠】
阿新 • • 發佈:2019-05-01
for 一個 tps href 是把 getchar() namespace tchar mes
狀態:
dp[i][j][k][0/1]
:
到達第i行時,
到達第j列時,
刷到第k次時,
這一格有沒有刷對
轉移
- 換一塊木板時肯定要多刷一次
dp[i][j][k][0]=max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1]);
dp[i][j][k][1]=max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1])+1;
- 當前格子與上一個格子顏色相同時
/* ,最優的方式是把前一個的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];//貪心,原封不動轉移
- 當前格子與上一個格子顏色不相同時
/*
[1]有兩個選擇: 一個是犧牲一次k換種顏色刷,另一個是繼續上一格的顏色
[0]也要貪心,因為這一格跟上一個不一樣,所以如果要繼續刷錯,可能是從上一次[1]原封不動過來,可能是再用一刷使得刷錯.
*/
dp[i][j][k][1]=max(dp[i][j-1][k-1][1],dp[i][j-1][k][0])+1;
dp[i][j][k][0]=max(dp[i][j-1][k][1],dp[i][j-1][k-1][0]);
代碼:
#include<bits/stdc++.h> using namespace std; int n,m,t; char p[55][55]; int dp[55][55][2501][2]; inline int read() { int tot=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { tot=tot*10+c-'0'; c=getchar(); } return tot; } int main() { n=read();m=read();t=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)cin>>p[i][j]; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { for(int k=1;k<=t;k++) { if(j==1) { dp[i][j][k][0]=max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1]); dp[i][j][k][1]=max(dp[i-1][m][k-1][0],dp[i-1][m][k-1][1])+1; continue; } if(p[i][j]==p[i][j-1]) { dp[i][j][k][1]=dp[i][j-1][k][1]+1; dp[i][j][k][0]=dp[i][j-1][k][0]; } else { dp[i][j][k][1]=max(dp[i][j-1][k-1][1],dp[i][j-1][k][0])+1; dp[i][j][k][0]=max(dp[i][j-1][k][1],dp[i][j-1][k-1][0]); } } } } cout<<max(dp[n][m][t][1],dp[n][m][t][0])<<endl; return 0; }
參考
這篇超棒的題解
題解 P4158 【[SCOI2009]粉刷匠】