Mine

Mine

Description

有一个 1 维的扫雷游戏,每个格子用*表示有雷,用 0/1/2 表示无

雷并且相邻格子中有 0/1/2 个雷。

给定一个仅包含?、*、0、1、2 的字符串 s,问有多少种方法将所

有的?改为*/0/1/2 使其合法。

Input

一行一个字符串 s。

Output

一行一个整数表示答案,对 10^9+7 取模。

Input 示例

?1?

Output 示例

2

数据范围

对于 30%的数据,|S|<=20。

对于 60%的数据,|S|<=1000。

对于 100%的数据,|S|<=10^6。

Solution

先讲最暴力的方法,对于每一位‘?’枚举该位填入什么,最后判断,时间复杂度为O(4^{|S|}),然而一看只有十分啊,所以这个显然是不行的,但是我们发现除了 当前一位填‘1’以外,填其他数字都可以确定左边和右边格子的情况,所以可以自然而然的想到dp,设dp[i][j][k]为填到第i位,前面一位填j,当前一位填k的方案数,这样的时间复杂度是O(4^2|S|),这样的时间复杂度其实已经可以卡过这道题,但我们再想一想可以发现,其实这样dp很多状态都是无意义的,所以我们可以把它展开,发现对于每一位最多只有五中状态,这样子复杂度就成O(4n)但对于dp状态的初始化,我们需要通过S的第一位来分别进行,代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#define Mod 1000000007
using namespace std;
char ch[1000010];
int dp[1000010][4][2];
int main(){
    freopen("mine.in","r",stdin);
    freopen("mine.out","w",stdout);
    scanf("%s",ch+1);
    int l=strlen(ch+1);
    if (ch[1]=='*') dp[0][2][1]=1;
    else if (ch[1]=='?') dp[0][2][1]=1,dp[0][1][0]=1;
    else dp[0][1][0]=1;
    for (int i=1;i<=l;i++){
        if (ch[i]=='?'){
            dp[i][0][0]=((dp[i-1][2][1]+dp[i-1][3][0])%Mod+dp[i-1][0][0])%Mod;
            dp[i][1][0]=(dp[i-1][1][0]+dp[i-1][2][0])%Mod;
            dp[i][2][0]=dp[i-1][0][0];
            dp[i][2][1]=(dp[i-1][2][0]+dp[i-1][1][0])%Mod;
            dp[i][3][0]=dp[i-1][0][0];
        }
        else{
            if (ch[i]=='*'){
                dp[i][0][0]=((dp[i-1][2][1]+dp[i-1][3][0])%Mod+dp[i-1][0][0])%Mod;
            }
            if (ch[i]=='0'){
                dp[i][1][0]=(dp[i-1][1][0]+dp[i-1][2][0])%Mod;
            }
            if (ch[i]=='1'){
                dp[i][2][0]=dp[i-1][0][0];
                dp[i][2][1]=(dp[i-1][2][0]+dp[i-1][1][0])%Mod;
            }
            if (ch[i]=='2'){
                dp[i][3][0]=dp[i-1][0][0];
            }
        }
    }
    int ans=0;
    ans=((dp[l][0][0]+dp[l][1][0])%Mod+dp[l][2][0])%Mod;
    printf("%d\n",ans);
    return 0;
}
阅读更多
个人分类: 动态规划
想对作者说点什么? 我来说一句

添加jsonMine类型

2014年01月13日 648B 下载

没有更多推荐了,返回首页

不良信息举报

Mine

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭