ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】CF149D Coloring Brackets(区间 DP,记忆化搜索)

2021-10-26 17:32:30  阅读:220  来源: 互联网

标签:MD Coloring Brackets int 题解 long 括号 染色 inline


Des

给出一个配对的括号序列(如"(())()"、"()"等, ")()"、"(()"是不符合要求的 ),对该序列按以下方法进行染色:

1.一个括号可以染红色、蓝色或不染色

2.一对匹配的括号需要且只能将其中一个染色

3.相邻两个括号颜色不能相同(但可以都不染色)

求符合条件的染色方案数(对1000000007取模)

\(\texttt{Data Range:}\)

2<=序列长度<=700

Sol

跟今年 [[【题解】P7914 括号序列(CSP-S2021)|CSP-S T2]] 如出一辙。

一个区间有两种转移方式,一是 (()),二是 ()...()。对于第二种方式直接转移会算重。

所以要记一个 \(g_{i,j}\) 数组表示上一次转移是 (()) 的括号序列的数列。然后在拼接 \(f_{i,j}\) 时,钦定左边是 \(g\),右边是 \(f\) 即可。原理相当于钦定从 \(i\) 匹配的右括号处转移。

注意需要记录首尾颜色,但这样会导致复杂度变成 \(O(350^3\times 81)\),需要尽可能的在代码中判断无效状态,并 continue 掉。

另一种方法是用记忆化搜索,不进入无效状态即可。

My code

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 705, MD = 1e9 + 7;
inline int add(int a, int b) { return a + b >= MD ? a + b - MD : a + b; }
inline int mul(int a, int b) { return (long long)a * b % MD; }
inline void Add(int &a, int b) { a = add(a, b); }
inline void Mul(int &a, int b) { a = mul(a, b); }
int n, f[N][N][3][3], g[N][N][3][3], ok[N][N];
char s[N];

int main() {
	scanf("%s", s + 1), n = strlen(s + 1);
	for(int i = 1; i <= n; i++) {
		int cnt = 0;
		for(int j = i; j <= n; j++) {
			if(s[j] == '(') ++cnt;
			else --cnt;
			if(cnt == 0) ok[i][j] = true;
		}
	}
	for(int i = 1; i < n; i++)
		if(s[i] == '(' && s[i + 1] == ')')
			for(int k = 1; k <= 2; k++)
				f[i][i + 1][0][k] = f[i][i + 1][k][0] = 1,
				g[i][i + 1][0][k] = g[i][i + 1][k][0] = 1;
	for(int len = 4; len <= n; len++) {
		for(int i = 1; i + len - 1 <= n; i++) {
			int j = i + len - 1;
			if(s[i] != '(' || s[j] != ')' || !ok[i][j]) continue;
			if(s[i + 1] == '(' && s[j - 1] == ')' && ok[i + 1][j - 1])
				for(int k = 1; k <= 2; k++)
					for(int q = 0; q < 3; q++)
						for(int h = 0; h < 3; h++) {
							if(h == k) continue;
							Add(f[i][j][0][k], f[i + 1][j - 1][q][h]);
							Add(g[i][j][0][k], f[i + 1][j - 1][q][h]);
							Add(f[i][j][k][0], f[i + 1][j - 1][h][q]);
							Add(g[i][j][k][0], f[i + 1][j - 1][h][q]);
						}
			for(int k = i + 1; k < j - 1; k++) {
				if(s[k] != ')' || s[k + 1] != '(' || !ok[i][k] || !ok[k + 1][j]) continue;
				for(int h = 0; h < 3; h++) for(int q = 0; q < 3; q++) {
					if(!g[i][k][h][q]) continue;
					for(int p = 0; p < 3; p++) for(int r = 0; r < 3; r++) {
						if((q == p && q != 0) || !f[k + 1][j][p][r]) continue;
						Add(f[i][j][h][r], mul(g[i][k][h][q], f[k + 1][j][p][r]));
					}	
				}
			}
		}
	}
	int ans = 0;
	for(int i = 0; i < 3; i++)
		for(int j = 0; j < 3; j++)
			Add(ans, f[1][n][i][j]);
	cout << ans << '\n';

	return 0;
}

标签:MD,Coloring,Brackets,int,题解,long,括号,染色,inline
来源: https://www.cnblogs.com/huaruoji/p/15466836.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有