然而这道题其实是DP。一直递推下去就好了:
那么我们现在来定义状态:
这里的DP与往常的不一样,我们要用i推到i+1;
用dp[i]表示我们前i个字符中的填问号的方案数:
只有这一维状态是显然不够的,因为前几个格子的状态会影响到这一格的,为了方便DP我们设置了如下的二维状态:
dp[i][0]:表示第i个格子和第i-1个格子都不填雷:
dp[i][1]:表示第i个格子不填雷,而第i-1个格子要填雷:
dp[i][2]:表示第i个格子要填雷:
只要状态定义出来了,方程气质就很简单了:
if(s[i]=='0')
dp[i+1][0]=dp[i][0];
else if(s[i]=='1')
dp[i+1][2]=dp[i][0],dp[i+1][0]=dp[i][1];
else if(s[i]=='2')
dp[i+1][2]=dp[i][1];
else if(s[i]=='*')
dp[i+1][2]=dp[i][2];
dp[i+1][1]=dp[i][2];
if (s[i]=='?')
dp[i+1][0]=(dp[i][0]+dp[i][1])%mod;
dp[i+1][2]=((dp[i][0]+dp[i][1])%mod+dp[i][2])%mod;
dp[i+1][1]=dp[i][2];
具体代码如下:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1001000 , mod = 1e9+7 ;
char s[maxn];
int dp[maxn][3];
int len;
void pre()
{
if (s[1]=='0') dp[2][0]=dp[1][0];
else if(s[1]=='1') dp[2][2]=dp[1][0];
else if(s[1]=='*') dp[2][1]=dp[1][2];
else if (s[1]=='?')
{
dp[2][1]=1;
dp[2][0]=1;
dp[2][2]=dp[2][1]+dp[2][0];
}
}
int main()
{
freopen("mine.in","r",stdin);
freopen("mine.out","w",stdout);
scanf("%s",s+1);
len=strlen(s+1);
dp[1][0]=1;
dp[1][1]=1;
dp[1][2]=1;
pre();
for(int i=2;i<=len;++i)
{
if(s[i]=='0')
dp[i+1][0]=dp[i][0];
else if(s[i]=='1') dp[i+1][2]=dp[i][0],dp[i+1][0]=dp[i][1];
else if(s[i]=='2') dp[i+1][2]=dp[i][1];
else if(s[i]=='*'){
dp[i+1][2]=dp[i][2];
dp[i+1][1]=dp[i][2];
}
if (s[i]=='?')
{
dp[i+1][0]=(dp[i][0]+dp[i][1])%mod;
dp[i+1][2]=((dp[i][0]+dp[i][1])%mod+dp[i][2])%mod;
dp[i+1][1]=dp[i][2];
}
}
printf("%d",(dp[len+1][0]+dp[len+1][1])%mod);
//for (register int i=1;i<=len;++i){
// for (register int j=0;j<=2;++j){
// printf ("%d ",dp[i][j]);
// }
// printf ("\n");
//}
return 0;
}