「火」皇家烈焰 (线性DP)

「火」皇家烈焰

题目描述 :
帕秋莉掌握了一种火属性魔法

由于钟爱扫雷游戏,帕秋莉把自己图书馆前的走廊看作一个一维的扫雷地图,她制造了很多烈焰,排在这条走廊内

现在帕秋莉告诉你一部分烈焰的分布情况,请你告诉她可能的情况有多少种

对于一个格子,里面会有以下几种字符:

0:这个格子没有烈焰,且其左右两个格子均没有烈焰

1:这个格子没有烈焰,且其左右两个格子中只有一个烈焰

2:这个格子没有烈焰,且其左右两个格子中均有烈焰

*:这个格子有烈焰

?:未告诉你本格情况

输入描述:
一个字符串 ,对于100%的数据,n≤1,000,000
输出描述:
输出一行,一个整数表示答案,对 1 e 9 + 7 1e9+7 1e9+7取模

很明显的线性DP,复杂度是 O ( n ) O(n) O(n) 的,题目以火为限制,那么我们根据每个位置是否有火来设dp状态,若 d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1] 代表前 i i i 位中第 i i i 位是否有火,但是此时的状态转移限制不仅来自于第 i − 1 i-1 i1位,还来自于 i + 1 i+1 i+1位,所以我们我们多增加一维 [ 0 / 1 ] [0/1] [0/1] 代表第 i + 1 i+1 i+1 位是否有火。只要状态找对了,接下来就按照题意转移就可。

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 1e6+7;
const int mod = 1e9+7;

int dp[N][2][2];  // dp[i][0/1][0/1] 代表前i位里,当前的i、i+1位是否有火,0代表无,1代表有; 
int main()
{
	string s;
	cin>>s;
	s = " "+s;
	int n = s.size()-1;
	dp[0][0][0] = dp[0][0][1] = 1 ;
	for(int i=1;i<=n;i++){
		if(s[i]=='0')      dp[i][0][0] += dp[i-1][0][0];  //均不为火
		else if(s[i]=='1'){   //i不为火,前后有一个为火
			dp[i][0][0] = (dp[i][0][0]+dp[i-1][1][0])%mod;
			dp[i][0][1] = (dp[i][0][1]+dp[i-1][0][0])%mod; 
		}else if(s[i]=='2'){   //i不为火 ,但是i前后都需要为火
			dp[i][0][1] = (dp[i][0][1]+dp[i-1][1][0])%mod;
		}else if(s[i]=='*'){	//i位为火,i前后均不确定
			dp[i][1][0] = (dp[i][1][0]+dp[i-1][0][1]+dp[i-1][1][1])%mod;
			dp[i][1][1] = (dp[i][1][1]+dp[i-1][0][1]+dp[i-1][1][1])%mod;
		}else if(s[i]=='?'){   //当此位为?时,前面的所有的状态都可以转移
			dp[i][0][0] = (dp[i][0][0]+dp[i-1][0][0]+dp[i-1][1][0])%mod;
			dp[i][0][1] = (dp[i][0][1]+dp[i-1][0][0]+dp[i-1][1][0])%mod; 
			dp[i][1][0] = (dp[i][1][0]+dp[i-1][0][1]+dp[i-1][1][1])%mod;
			dp[i][1][1] = (dp[i][1][1]+dp[i-1][0][1]+dp[i-1][1][1])%mod;
		}
	}
	cout<<(dp[n][0][0]+dp[n][1][0])%mod<<"\n";	//第n位为火和不为火的和
	return 0;
}
©️2020 CSDN 皮肤主题: 我行我“速” 设计师:Amelia_0503 返回首页