CF149D Coloring Brackets

Coloring Brackets

给出一个配对的括号序列,对该序列按以下方法进行染色:

  1. 一个括号可以染红色、蓝色或不染色。
  2. 一对匹配的括号需要且只能将其中一个染色。
  3. 相邻两个括号颜色不能相同(但可以都不染色)。

求符合条件的染色方案数对 \(10^9 + 7\) 取模。

算是比较难的区间 DP 题了。

\(f(l,r,0/1/2,0/1/2)\) 表示区间 \([l,r]\),首尾分别为 无色/红色/蓝色 的方案数。

转移分两种:

  1. \(l,r\) 的括号匹配,相当于求 \([l+1,r-1]\) 再反推回来。
  2. \(l\)\((l,r)\) 中的某个位置 \(k\) 匹配,相当于求 \([l,k],[k+1,r]\) 再考虑结合。

为了避免不合法状态的遍历,可以考虑使用记忆化搜索的方法,预处理一下每个左括号的匹配位,然后就非常好做了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 710;
const int MOD = 1e9 + 7;
int n, tot, s[N], match[N];
int f[N][N][3][3];
char str[N];

int read(){
	int x = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') f = (c == '-') ? -1 : 1, c = getchar();
	while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
	return x * f;
}

void dfs(int l, int r){
	if(f[l][r][0][1]) return;
	if(r == l + 1){
		f[l][r][0][1] = f[l][r][1][0] = 1;
		f[l][r][0][2] = f[l][r][2][0] = 1;
		return;
	}
	if(match[l] == r){
		dfs(l + 1, r - 1);
		for(int i = 0; i < 3; i ++)
			for(int j = 0; j < 3; j ++){
				if(i != 1) f[l][r][1][0] = (f[l][r][1][0] + f[l + 1][r - 1][i][j]) % MOD;
				if(i != 2) f[l][r][2][0] = (f[l][r][2][0] + f[l + 1][r - 1][i][j]) % MOD;
				if(j != 1) f[l][r][0][1] = (f[l][r][0][1] + f[l + 1][r - 1][i][j]) % MOD;
				if(j != 2) f[l][r][0][2] = (f[l][r][0][2] + f[l + 1][r - 1][i][j]) % MOD;
			}
		return;
	}
	else{
		int k = match[l];
		dfs(l, k), dfs(k + 1, r);
		for(int a = 0; a < 3; a ++)
			for(int b = 0; b < 3; b ++)
				for(int c = 0; c < 3; c ++)
					for(int d = 0; d < 3; d ++) if((b != c) || (!b))
						f[l][r][a][d] = (f[l][r][a][d] + 1LL * f[l][k][a][b] * f[k + 1][r][c][d] % MOD) % MOD;
		return;
	}
}

int main(){
	scanf("%s", str + 1); n = strlen(str + 1);
	for(int i = 1; i <= n; i ++)
		if(str[i] == '(') s[++ tot] = i;
		else match[s[tot --]] = i;
	dfs(1, n);
	int ans = 0;
	for(int i = 0; i < 3; i ++)
		for(int j = 0; j < 3; j ++)
			ans = (ans + f[1][n][i][j]) % MOD;
	printf("%d\n", ans);
	return 0;
}
posted @ 2021-07-18 21:42  LPF'sBlog  阅读(47)  评论(0编辑  收藏  举报