Codefoeces 404 D Minesweeper 1 D「小範囲後効性」dp

1981 ワード

タイトルリンク:http://codeforces.com/problemset/problem/404/D
标题:掃雷ゲームに似ていますが、行だけで、一部の格子は既知で、一部は未知で、'?'未知を表し、残りは既知である.'0'は左右に雷がないことを表し、'1'は左右に1つの雷があることを表し、'2'は左右に2つの雷があることを表し、'*'はそれ自体が雷であることを表す.合法的な状況は全部で何種類ありますか?(借りた題意)
ある状態が後の状態に影響される可能性があるように見えるが、後に影響を及ぼす状態は多くないため、この状態も現在のすべての状態に考慮して「後効性」を消す.
#include <iostream>   
#include <string>   
#include <cstring>   
#include <algorithm>   
#include <stdio.h>   
#include <cctype>   
#include <queue>   
#include <stdlib.h>   
#include <cstdlib>   
#include <math.h>   
#include <set>   
#include <vector>   
using namespace std; 
#define ll __int64
#define mod 1000000007

char s[3000005];
ll dp[1000005][5];
/*
0     0
1     1     
2     1     
3     2
4      

*/
int main(){
	ll i, j, k;
	while(~scanf("%s",s)){
		memset(dp[0], 0, sizeof(dp[0]));
		if(s[0]=='0')dp[0][0] = 1;
		else if(s[0]=='1')dp[0][2] = 1;
		else if(s[0]=='*')dp[0][4] = 1;
		else if(s[0]=='?')
			dp[0][0] = dp[0][2] = dp[0][4] = 1;

		for(i = 1; s[i]; i++){
			memset(dp[i], 0, sizeof(dp[i]));
			if(s[i] == '0'){
				dp[i][0] = dp[i-1][1] + dp[i-1][0];	dp[i][0] %= mod;
			}
			else if(s[i] == '1'){
				dp[i][1] = dp[i-1][4]; 
				dp[i][2] = dp[i-1][0] + dp[i-1][1];	dp[i][2] %= mod;
			}
			else if(s[i] == '2'){
				dp[i][3] = dp[i-1][4];
			}
			else if(s[i] == '*'){
				dp[i][4] = dp[i-1][2] + dp[i-1][3] + dp[i-1][4]; dp[i][4] %= mod;
			}
			else if(s[i] == '?'){
				dp[i][0] = dp[i-1][1] + dp[i-1][0];
				dp[i][1] = dp[i-1][4];
				dp[i][2] = dp[i-1][0] + dp[i-1][1];
				dp[i][3] = dp[i-1][4];
				dp[i][4] = dp[i-1][2] + dp[i-1][3] + dp[i-1][4];
				dp[i][0] %= mod; dp[i][4] %= mod; dp[i][2] %= mod;
			}
		}
		i--;
		ll ans = dp[i][0] + dp[i][1] + dp[i][4];
		printf("%I64d
", ans%mod); } return 0; }