洛谷 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 }

请各位大佬斧正(反正我不认识斧正是什么意思)

posted @ 2019-12-14 15:57  handsome_zyc  阅读(305)  评论(0编辑  收藏  举报