mine:dp

一个小的线性dp。方法很多,八仙过海各显神通。

我想讲一下我的:

 1 #include<cstdio>
 2 #define mod 1000000007
 3 char s[1000005];int dp[1000005][2][2],n;//是不是雷,右边有没有雷
 4 int main(){
 5     scanf("%s",s+1);
 6     for(n=1;s[n];n++);n--;
 7     dp[0][0][0]=dp[0][0][1]=1;
 8     for(int i=1;i<=n;++i)
 9         if(s[i]=='0')dp[i][0][0]=dp[i-1][0][0];
10         else if(s[i]=='1')dp[i][0][0]=dp[i-1][1][0],dp[i][0][1]=dp[i-1][0][0];
11         else if(s[i]=='2')dp[i][0][1]=dp[i-1][1][0];
12         else if(s[i]=='*')dp[i][1][1]=dp[i][1][0]=(dp[i-1][0][1]+dp[i-1][1][1])%mod;
13         else {
14             dp[i][0][0]=dp[i-1][0][0];//0
15             (dp[i][0][0]+=dp[i-1][1][0])%=mod;dp[i][0][1]=dp[i-1][0][0];//1
16             (dp[i][0][1]+=dp[i-1][1][0])%=mod;//2
17             dp[i][1][1]=dp[i][1][0]=(dp[i-1][0][1]+dp[i-1][1][1])%mod;//*
18         }
19     printf("%d\n",(dp[n][0][0]+dp[n][1][0])%mod);
20 }
先扔在这里

我的dp含义是:dp[i][this][next]表示考虑了第i位后,this和next位置上有没有雷的方案数。

思考一下:如果你知道前面的一位是什么,这一位是什么,你就能推断出下一位是什么。

因为在一维扫雷里只有相邻的3个格子之间有约束作用。

所以我们来考虑dp[i][t][n]由什么转移而来:

如果第i位是个’0‘,那么它不是雷它的前面一位不能是雷后面也不能是,则dp[i][0][0]=dp[i-1][0][0](注意文字与代码的颜色对应)

如果是个’1‘,那么它不是雷,分2种情况:

前面有后面没有:dp[i][0][0]=dp[i-1][1][0];

前面没有后面有:dp[i][0][1]=dp[i-1][0][0];

如果是个’2‘,那么它不是雷,而都有雷:dp[i][0][1]=dp[i-1][1][0];

如果它是个雷,那么前面随意。。后面也随意。。:dp[i][1][1]=dp[i][1][0]=dp[i-1][0][1]+dp[i-1][1][1];

如果是个问号就把上面这些状态都弄一遍就好。

初状态dp[0][0][0]=dp[0][0][1]=1因为第0个格子上没有雷而它的右边有没有再说并不会被第0个格子限制。

末状态dp[n][1][0]+dp[n][0][0]因为并不在意第n个格子上有没有雷(如果它不合法那么dp值为0),而第n+1个格子上没有雷。

完毕!

猜你喜欢

转载自www.cnblogs.com/hzoi-DeepinC/p/11364776.html