Minesweeper - 每天一把CF - 20201112
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;
}
相關文章
- 【Lintcode】1189. Minesweeper
- [20201112]time TIMEFORMAT格式.txtORM
- 002.07 MineSweeper - PySimleGUI 的應用GUI
- [20201112]tmpwatch 刪除檔案.txt
- [20201112]nid改變資料庫名字.txt資料庫
- CORS 一把梭CORS
- 用Python畫一把扇子Python
- [20201112]centos 7 rc.local shell script on systemd while booting Linux system.tCentOSWhilebootLinux
- CF提交
- 最近做題遇到的坑 cf865d,cf838e,cf317d,cf1394b,poj3322,cf223c,hdu2435,cf47d
- SVG-動畫的一把好手SVG動畫
- 我也來實現一把MVVMMVVM
- 體驗了一把快應用
- CF2041
- CF 979 ReviewView
- CF 977 ReviewView
- CF 1801 C
- CF 2008 H
- CF 1839 D
- CF 1913 D
- CF 1527 E
- CF1975
- CF1969
- CF1971
- CF700
- CF941
- CF1951
- cf12.4
- 每天給自己打分
- 終於做了一把MySQL調參boyMySql
- CSS核心概念一把梭-基礎部分CSS
- CF115E
- CF 1823 題解
- CF2042 E
- CF 1253 題解
- CF 705 題解
- CF1699E
- CF 構造題