CF - 404 - D. Minesweeper 1D(dp)

本文探讨了Codeforces竞赛中关于一维扫雷的问题,通过动态规划的方法,详细解释了如何计算符合特定规则的地图数量。

题意:一维扫雷,给出0, 1, 2, ?, *,问符合规则的地图有多少种 (长度:1 ≤ n ≤ 10^6)?

题目链接:http://codeforces.com/contest/404/problem/D

——>>怎么想呢?

看CF的代码看出了这样的想法:

设d[i][j]表示前i个位置(其中第i个位置是类型jj)的正确放置数。。

对于一个位置,共有3种类型:

0 : 该位置不是bomb,且下一个位置也不是bomb;

1 : 该位置不是bomb,且下一个位置是bomb;

2 : 该位置是bomb。

那么,可以得到状态转移方程:

设现在的位置是i,

一、如果是输入的0,

说明这个位置不是bomb,且下一个位置不是bomb,所以只会更新d[i][0],同时,上一个位置也不会是bomb,于是得:

d[i][0] = d[i-1][0];

二、如果是输入的1,

说明这个位置不是bomb,但下一个位置可能是bomb,如果下一个位置是bomb,那么上一个位置不会是bomb,则:

d[i][1] = d[i-1][0];

如果下一个位置不是bomb,那么上一个位置是bomb,则:

d[i][0] = d[i-1][2];

三、如果输入的是2,

说明这个位置不是bomb,下一个位置是bomb,所以只会更新d[i][1],且上一个位置是bomb,于是得:

d[i][1] = d[i-1][2];

四、如果输入的是*,

说明这个位置是bomb,上一个位置可以是bomb,也可以是1,则:

d[i][2] = d[i-1][2] + d[i-1][1];

五、如果输入的是?,

说明以上情况都可以,所以情况的数目都要加起来。。

************************************************************************

可以发现,d的第一维可以省略,用滚动数组的思想。。

#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 1000000 + 10;
const int mod = 1000000000 + 7;

char s[maxn];

int main()
{
    while(scanf("%s", s) == 1) {
        long long d[] = {1, 1, 0};
        for(int i = 0; s[i]; i++) {
            long long t[] = {0, 0, 0};
            if(s[i] == '0' || s[i] == '?') t[0] += d[0];
            if(s[i] == '1' || s[i] == '?') {
                t[1] += d[0];
                t[0] += d[2];
            }
            if(s[i] == '2' || s[i] == '?') t[1] += d[2];
            if(s[i] == '*' || s[i] == '?') t[2] += d[2] + d[1];
            for(int j = 0; j < 3; j++) d[j] = t[j] % mod;
        }
        printf("%I64d\n", (d[0] + d[2]) % mod);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值