D - Minesweeper 1D

Codeforces Round #237 (Div. 2) D - Minesweeper 1D

题意:类似于扫雷游戏,但只有行,有些格子是已知的,有些未知,‘?’表示未知,其余为已知。'0'表示左右都没有雷,'1'表示左右一共有一个雷,'2'表示左右一共有两个雷,‘*’表示本身就是雷。问合法的情况一共有多少种?

解题思路:这似乎也是可以算作是某一类dp了吧,我已经做到过若干道类似的题了。只是暂时还没人给它取名字。状态是dp[i][j],表示i位置符合j状态的有多少种合法状况。其中0<=i<len,0<=j<4。i表示在哪一个位置上,j=0表示i位置不是雷,i+1也不是雷,j=1表示i位置不是雷,但i+1是雷,j=2表示i位置是雷,i+1位置不是雷,j=3表示i和i+1都是雷。这么四种情况。然后就根据位置上的信息进行转移。方程如下:

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
#include <math.h>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#define lowbit(x) (x&(-x))
#define ll __int64
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define new_edge(a,b,c) edge[tot].t = b , edge[tot].v = c , edge[tot].next = head[a] , head[a] = tot ++
using namespace std;

const int maxn = 1111111 ;
const int mod = 1000000007 ;
ll dp[maxn][4] ;
char s[maxn] ;

int main() {
    int n , i , j , k ;
    scanf ( "%s" , s + 1 ) ;
    n = strlen ( s + 1 ) ;
    dp[0][0] = dp[0][1] = 1 ;
    for ( i = 1 ; i < n ; i ++ ) {
        if ( s[i] == '0' ) {
            dp[i][0] = dp[i-1][0] ;
        }
        if ( s[i] == '1' ) {
            dp[i][0] = dp[i-1][2] ;
            dp[i][1] = dp[i-1][0] ;
        }
        if ( s[i] == '2' ) {
            dp[i][1] = dp[i-1][2] ;
        }
        if ( s[i] == '*' ) {
            dp[i][2] = ( dp[i-1][1] + dp[i-1][3] ) % mod ;
            dp[i][3] = ( dp[i-1][1] + dp[i-1][3] ) % mod ;
        }
        if ( s[i] == '?' ) {
            dp[i][0] = ( dp[i-1][0] + dp[i-1][2] ) % mod ;
            dp[i][1] = ( dp[i-1][0] + dp[i-1][2] ) % mod ;
            dp[i][2] = ( dp[i-1][3] + dp[i-1][1] ) % mod ;
            dp[i][3] = ( dp[i-1][1] + dp[i-1][3] ) % mod ;
        }
    }
//    for ( i = 1 ; i < n ; i ++ )
  //      for ( j = 0 ; j < 4 ; j ++ )
   //         printf ( "dp[%d][%d] = %I64d\n" , i , j , dp[i][j] ) ;
    ll ans ;
    if ( s[n] == '0' ) {
        ans = dp[n-1][0] ;
    }
    else if ( s[n] == '1' ) {
        ans = dp[n-1][2] ;
    }
    else if ( s[n] == '2' ) {
        ans = 0 ;
    }
    else if ( s[n] == '*' ) {
        ans = ( dp[n-1][1] + dp[n-1][3] ) % mod ;
    }
    else {
        ans = ( dp[n-1][0] + dp[n-1][1] + dp[n-1][2] + dp[n-1][3] ) % mod ;
    }
    printf ( "%I64d\n" , ans ) ;
    return 0;
}

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值