Coloring Brackets CodeForces - 149D

设dp[l][r][x][y]表示区间[l,r]左端染的色是x,右端染的色是y的方案数
其中x,y取0,1,2,分别表示不染色,染红色,染蓝色

1.l+1==r,那么它们一定就是一对匹配的括号,因为我们枚举的都是合理的情况,此时,只可能有四种情况,方案数均为1,即:dp[l][r][0][1] = dp[l][r][1][0] = 1;dp[l][r][0][2] = dp[l][r][2][0] = 1;
2.l和r是一对匹配的括号,此时,区间被分为两部分,两端点以及区间[l+1,r-1],那么我们可以先算出区间[l+1,r-1]的方案数,再由此状态转移到当前区间,两端点情况也就四种,不冲突即可转移
3.l和r不是一对匹配的括号,此时,区间也可被分成两部分,区间[l,mid]和区间[mid+1,r],其中mid为l所对应与之匹配的括号,这样,一个合法的括号序列变成两个合法的括号序列,将它们分别求出方案数,再将不冲突的情况组合起来即可

//设dp[l][r][x][y]表示区间[l,r]左端染的色是x,右端染的色是y的方案数
//其中x,y取0,1,2,分别表示不染色,染红色,染蓝色

#include<iostream> 
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 705;
const int mod = 1000000007;
ll dp[maxn][maxn][3][3];
string str;
stack<int> s;
map<int, int> pos;
//找当前括号对应匹配括号的下标
void get_match() {
	for (int i=0; i<str.size(); ++i) {
		if (str[i] == '(')
			s.push(i);
		else {
			pos[i] = s.top();
			pos[s.top()] = i;
			s.pop();
		}
	}
}

void dfs(int l, int r) {
	//当区间长度只有2时候
	//两个括弧一定是配对的,因为我们考虑的所有区间都是配对合法的区间
	//
	if (l+1 == r) {
		dp[l][r][0][1] = dp[l][r][1][0] = 1;
		dp[l][r][0][2] = dp[l][r][2][0] = 1;
		return ;
	}
	//如果是匹配区间
	if (pos[l] == r) {
		//算里面的区间
		dfs(l+1, r-1);
		for (int i=0; i<3; ++i)
			for (int j=0; j<3; ++j) {
				//枚举所有情况,相邻的颜色不能相同 ,可以相邻两边都不染色
				//但匹配的括号里面必须有一个染色,且只能由一个染色
				//当区间尾部染色不为1
				if (j != 1)
					//开头不染,末尾染1
					//								开头可以不染,但末尾颜色不能为1
					dp[l][r][0][1] = (dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod;
				if (j != 2)
					dp[l][r][0][2] = (dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod;
				if (i != 1)
					dp[l][r][1][0] = (dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod;
				if (i != 2)
					dp[l][r][2][0] = (dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod;
			}
		return ;
	}
	//如果不是匹配区间
	//去找匹配区间
	int mid = pos[l];
	dfs(l, mid);
	dfs(mid+1, r);
	//将两边的情况合并
	for (int i=0; i<3; ++i)
		for (int j=0; j<3; ++j)
			for (int k=0; k<3; ++k)
				for (int s=0; s<3; ++s)
					if (!(k==1&&s==1) && !(k==2&&s==2))
						dp[l][r][i][j] = (dp[l][r][i][j]+dp[l][mid][i][k]*dp[mid+1][r][s][j])%mod;
}

int main() {
	cin >> str;
	get_match();
	dfs(0, str.size()-1);
	ll ans = 0;
	for (int i=0; i<3; ++i)
		for (int j=0; j<3; ++j)
			ans = (ans+dp[0][str.size()-1][i][j])%mod;
	cout << ans << endl;
	return 0;
}
posted @ 2020-03-12 14:41  晴屿  阅读(96)  评论(0编辑  收藏  举报