Minesweeper - 每天一把CF - 20201112

北北北喜歡流浪發表於2020-11-13

2020-11-12

dp

404D 1900

題目

原題連結:https://codeforces.com/problemset/problem/404/D

在這裡插入圖片描述

思路

題目大意:一維掃雷遊戲,只有一行,每個位置有012*四種可能性,前三個數字表示周圍兩個位置炸彈的數量,*就表示炸彈。

現在有一個未完成的一維掃雷地圖,其中有些位置是?,?可以任意放以上任意一種(只要符合規則),問共有多少种放法。

思路:題目明顯的可以看出每個位置上有四種可能性,有嘗試的影子,所以我們可以直接拿一維來表示這四種狀態。

即012分別代表放對應的數字,然後3代表放炸彈的狀態。

但是我們再次思考,如果是1,我們又要去判斷這個1到底前面是炸彈還是後面是炸彈。在狀態轉移的時候會造成很多困擾,我們不妨再將1的這兩個狀態分別儲存----這也是這道題我認為精華的部分!

所以最終我們可以將狀態設定為

	0表示字串下標為i的元素為0
	1表示元素為1且前一個元素為地雷
	2表示元素為1且前一個元素非地雷(0 / 1)
	3表示元素為地雷
	4表示元素為’2’

如此,可解。

程式碼實現

AC程式碼

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <string>
using namespace std;

#define mes0(c) memset((c),0,sizeof(c))
#define mesi(c) memset((c),ifi,sizeof(c))
#define fsios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define rep1(n) for (int i=1;i<=(n);i++)
#define rep2(n) for (int j=1;j<=(n);j++)
#define inp(a, n) for (int i = 1; i <= (n); i++) cin >> a[i];
#define ll long long
#define fi first
#define se second

const ll MAX = 1e6 + 5;
//const int ifi = 0x3f3f3f3f;
const int mod = 1e9 + 7;

char s[MAX];
ll dp[MAX][5];
/*
	0表示字串下標為i的元素為0
	1表示元素為1且前一個元素為地雷
	2表示元素為1且前一個元素非地雷(0 / 1)
	3表示元素為地雷
	4表示元素為’2’
*/

int main() {
	fsios;
	while (cin >> s) {
		int len = strlen(s);

		if (s[0] == '0') dp[0][0] = 1;
		else if (s[0] == '1') dp[0][2] = 1;
		else if (s[0] == '*') dp[0][3] = 1;
		else if (s[0] == '?') {
			dp[0][0] = 1;
			dp[0][3] = 1;
			dp[0][2] = 1;
		}

		for (int i = 1; i < len; i++)
		{
			if (s[i] == '0') {
				dp[i][0] = (dp[i - 1][0] % mod + dp[i - 1][1] % mod) % mod;
			}
			if (s[i] == '1') {
				dp[i][1] = (dp[i - 1][3] % mod);
				dp[i][2] = (dp[i - 1][0] % mod + dp[i - 1][1] % mod) % mod;
			}
			if (s[i] == '*') {
				dp[i][3] = (dp[i - 1][2] + dp[i - 1][3] + dp[i - 1][4]) % mod;
			}
			if (s[i] == '2') {
				dp[i][4] = (dp[i - 1][3] % mod) % mod;
			}
			if (s[i] == '?') {
				dp[i][0] = (dp[i - 1][0] % mod + dp[i - 1][1] % mod) % mod;
				dp[i][1] = (dp[i - 1][3] % mod) % mod;
				dp[i][2] = (dp[i - 1][0] % mod + dp[i - 1][1] % mod) % mod;
				dp[i][3] = (dp[i - 1][2] % mod + dp[i - 1][3] % mod + dp[i - 1][4] % mod) % mod;
				dp[i][4] = (dp[i - 1][3] % mod) % mod;
			}
		}
		ll ans = 0;
		len--;
		ans = dp[len][0] % mod + dp[len][1] % mod + dp[len][3] % mod;
		cout << ans % mod << endl;
		mes0(s);
		mes0(dp);
	}
	return 0;
}