CF404D Minesweeper 1D(dp)

题目链接:D. Minesweeper 1D 【一维扫雷】

题意:

一维扫雷,每个位置可能为'0', '1', '2', '*'。‘*’表示雷,0 1 2 都表示其左右的雷的数量,现在给出一个一维扫雷的地图(|s|<=1e6),其中有一些字符'?',这些‘?’可以是以上四个值的任意一种,问有多少种合法的地图。

输入样例:

?01???

输出样例:

4

输入样例:

?

输出样例:

2

题目分析:

对于每个位置,要么是雷,要么不是雷,但是数字会限制其左右的雷的数量。

如果前一个位置为数字,假设左边情况已经是已知的,那么这一位是否为雷也是确切的。

如果前一个位置为雷,那么这个位置可以为雷,也可以为数字。

定义一下三种状态,

0:这一位不是雷。下一位不是雷。

1:这一位不是雷。下一位是雷。

2:这一位是雷。下一位可以是雷,也可以不是雷。

dp初始条件是dp[0][0] = dp[1][0] = 1;

初始位置下标1前面是没有雷的,但是下标1可以是雷也可以不是雷

那么转移dp[i]的方式就取决于s[i]是什么了,分类讨论即可

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
int n, p;
typedef pair<int,int> P;
char s[MAXN];
int dp[MAXN][3];
//0:x/x  1:x/*  2:*/?
inline void ADD(int &a, int &b){
    a += b; if(a >= mod) a-= mod;
}
int main(){
    scanf("%s",s+1);
    n = strlen(s+1);
    dp[0][0] = dp[0][1] = 1;
    for(int i = 1;i<=n;i++){
        if(s[i] == '0' || s[i] == '?'){
            ADD(dp[i][0], dp[i-1][0]);
        }
        if(s[i] == '1' || s[i] == '?'){
            ADD(dp[i][1], dp[i-1][0]);
            ADD(dp[i][0], dp[i-1][2]);
        }
        if(s[i] == '2' || s[i] == '?'){
            ADD(dp[i][1], dp[i-1][2]);
        }
        if(s[i] == '*' || s[i] == '?'){
            ADD(dp[i][2], dp[i-1][1]);
            ADD(dp[i][2], dp[i-1][2]);
        }
    }
    ADD(dp[n][0],dp[n][2]);
    printf("%d\n",dp[n][0]);
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值