码迷,mamicode.com
首页 > 其他好文 > 详细

【每日一题】25.「火」皇家烈焰 (字符串DP)

时间:2021-05-24 08:32:39      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:tar   code   target   初始   mod   转移   acm   ==   long   

补题链接:Here

技术图片

转移方程的具体含义我在代码注释里写出来了, 很好理解
这道题的难点在于如何表示状态, 一旦找到状态表示方法
只要根据题意做转移就行了
最后的答案就是 \(dp[n][0][0] + dp[n][1][0]\)
即最后一个位置有火的方案数加上最后一个位置没有火的方案数
注意不要忘了一开始的初始化 \(dp[0][0][0] = dp[0][0][1] = 1\)

using ll = long long;
const int mod = 1e9 + 7, N = 1e6 + 10;
ll dp[N][2][2];
void solve() {
	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], dp[i][0][0] %= mod;
		}
		else if (s[i] == ‘1‘) { // 当前无 左右 有一个
			dp[i][0][0] += dp[i - 1][1][0]; dp[i][0][0] %= mod; // 左有
			dp[i][0][1] += dp[i - 1][0][0], dp[i][0][1] %= mod; // 右有
		}
		else if (s[i] == ‘2‘) { // 当前无 左右均有
			dp[i][0][1] += dp[i - 1][1][1], dp[i][0][1] %= mod; // 左右有
		}
		else if (s[i] == ‘*‘) { // 当前有 左右任意
			dp[i][1][0] += (dp[i - 1][0][1] + dp[i - 1][1][1]),
			               dp[i][1][0] %= mod; // 当前有 右无 然后 左有或者没有
			dp[i][1][1] += (dp[i - 1][0][1] + dp[i - 1][1][1]),
			               dp[i][1][1] %= mod; // 当前有 右有 然后 左有或者没有
		}
		else if (s[i] == ‘?‘) { // 当前任意
			dp[i][1][0] += (dp[i - 1][0][1] + dp[i - 1][1][1]),
			               dp[i][1][0] %= mod; // 当前为火 右无
			dp[i][1][1] += (dp[i - 1][0][1] + dp[i - 1][1][1]),
			               dp[i][1][1] %= mod; // 当前和右 为火
			dp[i][0][1] += (dp[i - 1][0][0] + dp[i - 1][1][0]),
			               dp[i][0][1] %= mod; // 当前无 右火
			dp[i][0][0] += (dp[i - 1][0][0] + dp[i - 1][1][0]),
			               dp[i][0][0] %= mod; // 当前无 右无
		}
	}
	cout << (dp[n][1][0] + dp[n][0][0]) % mod <<
	     "\n"; // 最后一格有 和 无的方案
}

【每日一题】25.「火」皇家烈焰 (字符串DP)

标签:tar   code   target   初始   mod   转移   acm   ==   long   

原文地址:https://www.cnblogs.com/RioTian/p/14766617.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!