【每日一题】5月7日题目精讲 「火」皇家烈焰
链接:
「火」皇家烈焰
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
帕秋莉掌握了一种火属性魔法
由于钟爱扫雷游戏,帕秋莉把自己图书馆前的走廊看作一个一维的扫雷地图,她制造了很多烈焰,排在这条走廊内
现在帕秋莉告诉你一部分烈焰的分布情况,请你告诉她可能的情况有多少种
对于一个格子,里面会有以下几种字符:
0:这个格子没有烈焰,且其左右两个格子均没有烈焰
1:这个格子没有烈焰,且其左右两个格子中只有一个烈焰
2:这个格子没有烈焰,且其左右两个格子中均有烈焰
*:这个格子有烈焰
?:未告诉你本格情况
输入描述:
一个字符串
输出描述:
输出一行,一个整数表示答案,对1e9+7取模
示例1
输入
?1?
输出
2
说明
已知第二个格子左右有一个烈焰
因此可能的情况有10和01,显然其他情况都无法满足已知条件的要求
备注:
字符串的长度为n
对于30%的数据,n≤20
对于60%的的数据,n≤1,000
对于100%的数据,n≤1,000,000
题解:
乍一看以为是扫雷。仔细一看为什么又是dp(每日一题好爱出dp,而我dp又是渣渣)
在其他大佬那吸取知识之后,写出自己的理解:
我们仔细看题可以看出,每个点什么情况其实都与两侧的点息息相关,我可以通过一个点算出两侧点的状态,也可以根据两侧状态来反推中间的点。
但是我们状态转移的顺序是从左到右,我们在转移过程中,考虑第i点时,i-1之前的点状态都是固定的,所以我们只需要考虑当前点i与之后一个点i+1的状态。
在第i点时,i+1可能也有了要求,所以不满足情况的就不用转移状态。
dp[i][0/1/2/3]:
0表示i与i+1都不是火
1表示i是火,i+1不是火
2表示i不是火,i+1是
3表示i和i+1都是火
对照题目给出的状态,
0:这个格子没有烈焰,且其左右两个格子均没有烈焰
1:这个格子没有烈焰,且其左右两个格子中只有一个烈焰
2:这个格子没有烈焰,且其左右两个格子中均有烈焰
*:这个格子有烈焰
?:未告诉你本格情况
具体情况如下:
if(i = = 0)
说明i-1,i,i+1都没有火,i 的状态就是等同于i-1的状态都是0(即本身与右边都不是火)
转移方程:f [i ] [ 0 ] = f [ i - 1 ] [ 0 ]
if(i = = 1)
i不是火,但是i的周围有一个火
如果左边是火,那么右边就不是火,那i就满足状态0,i-1就满足状态1:f[i][0]=f[i-1][1]
如果右边是火,左边就不是火,那么i就满足状态2,i-1就满足状态0:f [ i ][ 2 ] = f [ i - 1 ] [ 0]
if(i = = 2)
左右均为火,那么i-1是火,i不是火,i+1是火,i就满足状态2: f [ i ] [ 2 ] =f [ i-1 ] [ 1 ]
if(i = = *)
当前i为火,I+1有两种情况,
一个是i+1位火:
f [ i ] [ 3 ]= f [ i - 1 ] [ 2 ] + f [ i - 1 ] [ 3 ]
i+1不是火:
f [ i ] [ 1 ] = f [ i - 1 ] [ 2 ] + f [ i - 1 ] [ 3 ]
if(i = = ?)
当前点未知,我们就要考虑所有情况
i为火,i不为火,i+1为火,i+1不为火
四种情况:
i与i+1都不是火:
f [ i ] [0 ] = f[ i - 1 ][ 0 ] + f [i - 1 ] [ 1 ]
i不是,i+1是火
f [ i ] [ 2 ] = f [ i - 1 ] [ 0 ] + f [ i - 1 ] [ 1 ]
i是火,i+1不是
f [ i ] [ 1 ] = f [ i - 1 ] [ 2 ] + f [i - 1 ] [ 3 ]
i和i+1都是火
f [ i ] [ 3 ] = f [ i - 1 ] [ 2 ] + f [ i - 1 ][ 3 ]
到最后一个点i,i后面没有点了,相当于i+1不是火
答案就是
i是火与不是火了两种情况加一起
f [ i ] [ 0 ] + f [ i ] [ 1 ]
此时i=地图长度
对了前往不要忘了取模mod
结合我讲的,在代码里面一条一条对应
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1,mod=1e9+7;
int f[maxn][7];
char s[maxn];
int main()
{
f[0][0]=f[0][2]=1;
cin>>s;
int len=strlen(s);
for(int i=1;i<=len;++i)
{
if(s[i-1]=='0')
{
f[i][0]=f[i-1][0];
}
else if(s[i-1]=='1')
{
f[i][0]=f[i-1][1];
f[i][2]=f[i-1][0];
}
else if(s[i-1]=='2')
{
f[i][2]=f[i-1][1];
}
else if(s[i-1]=='*'){
f[i][1]=(f[i-1][2]+f[i-1][3])%mod;
f[i][3]=(f[i-1][2]+f[i-1][3])%mod;
}
else if(s[i-1]=='?'){
f[i][0]=(f[i-1][0]+f[i-1][1])%mod;
f[i][2]=(f[i-1][0]+f[i-1][1])%mod;
f[i][1]=(f[i-1][2]+f[i-1][3])%mod;
f[i][3]=(f[i-1][2]+f[i-1][3])%mod;
}
}
cout<<(f[len][0]+f[len][1])%mod;
return 0;
}