zoukankan      html  css  js  c++  java
  • [10.10模拟] mine

    题意:

    有一个 1 维的扫雷游戏,每个格子用表示有雷,用 0/1/2 表示无雷并且相邻格子中有 0/1/2 个雷。给定一个仅包含?、、0、1、2 的字符串 s,问有多少种方法将所有的?改为*/0/1/2 使其合法。

    题解:

    dp

    这题告诉我,设计好一个状态是多么重要

    考场上设dp[i][4],转移了一个上午,到最后还是拍wa了,只好弃疗

    看了菊神的dp状态,感觉我是头猪

    g[i][0]表示到第i位,这一位一定不选雷,前一位不是雷的方案数,g[i][1]表示这一位一定不选雷,前一位是雷的方案数,f[i]表示这一位一定选雷的方案数

    这样设状态就没有局限性了,根据*/0/1/2的性质直接转移就可以了,我那样一个一个设是有局限性的

    ps:dp的时候用状态转移的思想有时会更加方便,这使我领略到了dp和递推的区别(请允许我瞎yy)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define N 1000010
    #define mo 1000000007
    using namespace std;
    
    ll f[N],g[N][2];
    char s[N];
    
    int gi() {
      int x=0,o=1; char ch=getchar();
      while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
      if(ch=='-') o=-1,ch=getchar();
      while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
      return o*x;
    }
    
    int main() {
      scanf("%s", s+1);
      int n=strlen(s+1);
      if(s[1]=='*') g[2][1]++;
      if(s[1]=='0') g[2][0]++;
      if(s[1]=='1') f[2]++;
      if(s[1]=='?') f[2]+=2,g[2][0]++,g[2][1]++;
      for(int i=2; i<=n; i++) {
        if(s[i]=='0') g[i+1][0]=g[i][0];
        else  if(s[i]=='1') f[i+1]=g[i][0],g[i+1][0]=g[i][1];
        else if(s[i]=='2') f[i+1]=g[i][1];
        else if(s[i]=='*') f[i+1]=f[i],g[i+1][1]=f[i];
        else {
          g[i+1][0]=(g[i][0]+g[i][1])%mo;
          g[i+1][1]=f[i];
          f[i+1]=(g[i][0]+g[i][1]+f[i])%mo;
        }
      }
      printf("%lld
    ", (g[n+1][0]+g[n+1][1])%mo);
      return 0;
    }
    
  • 相关阅读:
    第二章函数对象
    2013/10/24初学BOOST
    [转]delete 多表删除的使用
    vs2010配置boost编程环境(照抄并简化)
    游戏服务器修改状态标志位方法
    小思 引用和指针
    第二章:UNIX标准化及实现
    const指针
    第一章:UNIX基础知识
    基础算法——位运算
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7648280.html
Copyright © 2011-2022 走看看