扫雷

题目

思想- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 模拟

枚举出所有的可能性: 到当前状态的方案数+=能到它的状态的方案数

(具体有哪几种情况下面有详解)

代码- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#define mod 1000000007
using namespace std;
char c[1000010];
long long f[1000010][4][2],tmp;//0表示i为0,1表示i为1,2表示i为2,3表示i为*.0表示i-1不为*,1表示i-1为* 
int main(){
    scanf("%s",c+1);//c第一位为 1 
    int l=strlen(c+1);
    if(c[1]=='1'||c[1]=='?') f[1][1][0]=1;//初定义:无论它们第一位是什么,前一位都没得选,便定为'*' 
    if(c[1]=='2'||c[1]=='?');//第一位不可能为 2,因为它不可能两边都是'*' 
    if(c[1]=='0'||c[1]=='?') f[1][0][0]=1;
    if(c[1]=='*'||c[1]=='?') f[1][3][0]=1;
    for(int i=2;i<=l;i++){
        if(c[i]=='1'||c[i]=='?'){
            f[i][1][0]=(f[i][1][0]+f[i-1][1][1]+f[i-1][0][0])%mod;//到达这种状态的几种方法 
            f[i][1][1]=(f[i][1][1]+f[i-1][3][0]+f[i-1][3][1])%mod;
        }
        if(c[i]=='2'||c[i]=='?'){
            f[i][2][1]=(f[i][2][1]+f[i-1][3][0]+f[i-1][3][1])%mod;
        }
        if(c[i]=='0'||c[i]=='?'){
            f[i][0][0]=(f[i][0][0]+f[i-1][1][1]+f[i-1][0][0])%mod;
        }
        if(c[i]=='*'||c[i]=='?'){
            f[i][3][0]=(f[i][3][0]+f[i-1][1][0]+f[i-1][2][1])%mod;
            f[i][3][1]=(f[i][3][1]+f[i-1][3][0]+f[i-1][3][1])%mod; 
        }
    }
    //注:因为不存在这两种情况:···2 或 ···f 1(f表示一个不是'*'的数)所以最后不用加这两种情况 
    tmp=(f[l][3][0]+f[l][3][1]+f[l][1][1]+f[l][0][0])%mod;
    printf("%lld",tmp);
}

代码详解- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

f[ i ][ j ][ k ]: i 表示当前是第几个字符;j 表示这个字符是什么:' 0、1、2、* ' -> 0、1、2 、3('?'是什么都无所谓);k 表示前一位字符是否为 ' * '(0:Χ   1:√)

有以下几种情况(f为0、1、2中的一个):

  1.当 c[i]=0或? 时:

  ······0 0 0····· 或······* 1 0                                                           ->f[i][0][0]+=f[i-1][0][0]+f[i-1][1][1]

  2.当 c[i]=1或? 时:

    • c[i-1]=='*': ······f * 1······ 或 ······* * 1······                           ->f[i][1][1]+=f[i-1][3][0]+f[i-1][3][1]
    • c[i-1]!='*': ······f 0 1······ 或 ······* 1 1······                           ->f[i][1][0]+=f[i-1][0][0]+f[i-1][1][1]

       3.当 c[i]=2或?时:

  ······f * 2······ 或 ······* * 2······                                                     ->f[i][2][1]+=f[i-1][3][0]+f[i-1][3][1]

  4.当 c[i]='*'或?时:

    • c[i-1]=='*': ······1 * *······ 或 ······* * *······                            ->f[i][3][1]+=f[i-1][3][1]+f[i-1][3][1]
    • c[i-1]!='*': ······f 1 *······ 或 ······* 2 *······                             ->f[i][3][0]+=f[i-1][1][0]+f[i-1][2][1]

 最后:因为不存在这两种情况:······2 或 ······f 1,所以 

tmp=f[l][3][0]+f[l][3][1]+f[l][1][1]+f[l][0][0]
原文地址:https://www.cnblogs.com/lxy050129/p/10729275.html