开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情
牛客小白月赛19 J题「火」皇家烈焰
题目描述:
帕秋莉掌握了一种火属性魔法 由于钟爱扫雷游戏,帕秋莉把自己图书馆前的走廊看作一个一维的扫雷地图,她制造了很多烈焰,排在这条走廊内 现在帕秋莉告诉你一部分烈焰的分布情况,请你告诉她可能的情况有多少种 对于一个格子,里面会有以下几种字符:
- 0:这个格子没有烈焰,且其左右两个格子均没有烈焰
- 1:这个格子没有烈焰,且其左右两个格子中只有一个烈焰
- 2:这个格子没有烈焰,且其左右两个格子中均有烈焰
- *:这个格子有烈焰
- ?:未告诉你本格情况
输入描述: 一个字符串
输出描述: 输出一行,一个整数表示答案,对1e9+7取模
题解分析:
分析几维DP:首先这道题显然的dp题目,状态转移的时候,与前一位,当前位,后一位都有关系,所以开三维DP
即:f[i][0/1][0/1]
分别表示:f[前i位][当前位是否有雷][后一位是否有雷]
(其中0表示没雷,1表示有雷)
初始化:f[0][0][0]=1,f[0][0][1]=1
分类讨论:
如果s[i]=0 ,那么代表,当前位,前一位,后一位均无雷
状态转移方程为:f[i][0][0]+=f[i-1][0][0]%mod
如果 s[i]=1 ,那么代表,当前位无雷,前一位有雷或者后一位有雷,
状态转移方程为:
如果是前一位有雷,后一位无雷:f[i][0][0]+=f[i-1][1][0]%mod
如果是前一位无雷,后一位有雷:f[i][0][1]+=f[i-1][0][0]%mod
如果s[i]=2 ,那么代表,当前位无雷,前一位和后一位均有雷
状态转移方程为:f[i][0][1]+=f[i-1][1][0]%mod
如果s[i]=*,那么代表,当前位有雷,前一位后一位不清楚
状态转移方程为:
如果后一位无雷:f[i][1][0]+=(f[i-1][0][1]+f[i-1][1][1])%mod
如果后一位有雷:f[i][1][1]+=(f[i-1][0][1]+f[i-1][1][1])%mod
如果s[i]=?,那么当前位置不知道,就需要讨论所有情况
如果当前位有雷,下一位无雷:f[i][1][0]+=(f[i-1][0][1]+f[i-1][1][1])%mod
如果当前位有雷,下一位有雷:f[i][1][1]+=(f[i-1][0][1]+f[i-1][1][1])%mod
如果当前位无雷,下一位无雷:f[i][0][0]+=(f[i-1][0][0]+f[i-1][1][0])%mod
如果当前位无雷,下一位有雷:f[i][0][1]+=(f[i-1][0][0]+f[i-1][1][0])%mod
输出:(f[n][1][0] + f[n][0][0]) % mod 即可
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
const int mod = 1e9 + 7;
int f[N][2][2];
int main() {
string s;
cin >> s;
s = " " + s;
int n = s.size() - 1;
f[0][0][0] = 1, f[0][0][1] = 1;
for (int i = 1; i <= n; i++) {
if (s[i] == '0') f[i][0][0] += f[i - 1][0][0] % mod;
else if (s[i] == '1') {
f[i][0][0] += f[i - 1][1][0] % mod;
f[i][0][1] += f[i - 1][0][0] % mod;
} else if (s[i] == '2') f[i][0][1] += f[i - 1][1][0] % mod;
else if (s[i] == '*') {
f[i][1][0] += (f[i - 1][0][1] + f[i - 1][1][1]) % mod;
f[i][1][1] += (f[i - 1][0][1] + f[i - 1][1][1]) % mod;
} else if (s[i] == '?') {
f[i][1][0] += (f[i - 1][0][1] + f[i - 1][1][1]) % mod;
f[i][1][1] += (f[i - 1][0][1] + f[i - 1][1][1]) % mod;
f[i][0][0] += (f[i - 1][0][0] + f[i - 1][1][0]) % mod;
f[i][0][1] += (f[i - 1][0][0] + f[i - 1][1][0]) % mod;
}
}
cout << (f[n][0][0] + f[n][1][0]) % mod << endl;
return 0;
}