Coloring Brackets[*1900] [区间DP] [DFS]

Coloring Brackets[*1900] [区间DP] [DFS]

Problem - D - Codeforces

三个要求

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

遇到括号配对我们可以用stack来存储配对
数据结构的栈和队列应该刚讲了

然后可以用一个match数组来存储配对的下标

动态规划的关键就是一个大问题可以划分成几个不干扰的子问题
最后再进行合并

显然这个题的子问题可以划分成更小的可以配对的序列
这就可以依赖于刚才的match数组来实现

我们的动态转移方程中还需要携带状态
我们应该携带什么状态呢?

回头再看题目中的三个条件

显然我们可以携带边界的颜色来进行判断
将不染色 红色蓝色映射成0 1 2
由此便可以推出状态转移方程

因为子区间的划分是无序的
因此可以用DFS划分解决这道问题

key code

int n,m;
const int maxn=710;
const int mod=1e9+7;
char s[maxn];
int dp[maxn][maxn][3][3];
int match[maxn];
stack<int>S;
void dfs(int l,int r){
	if(l+1==r){
		dp[l][r][0][1]=
		dp[l][r][0][2]=
		dp[l][r][1][0]=
		dp[l][r][2][0]=1;
	}
	else if(match[l]==r){
		dfs(l+1,r-1);
		fup(i,0,2)fup(j,0,2){
			if(j!=1)(dp[l][r][0][1]+=dp[l+1][r-1][i][j])%=mod;
			if(j!=2)(dp[l][r][0][2]+=dp[l+1][r-1][i][j])%=mod;
			if(i!=1)(dp[l][r][1][0]+=dp[l+1][r-1][i][j])%=mod;
			if(i!=2)(dp[l][r][2][0]+=dp[l+1][r-1][i][j])%=mod;
		}
	}
	else{
		dfs(l,match[l]);
		dfs(match[l]+1,r);
		fup(i,0,2)
		fup(j,0,2)
		fup(p,0,2)
		fup(q,0,2)
		if(j!=p||(j==p&&j!=1&&j!=2))
		(dp[l][r][i][q]+=dp[l][match[l]][i][j]*dp[match[l]+1][r][p][q])%=mod;
	}
}
void solve(){
	//try it again.
	cin>>s;
	n=strlen(s);
	up(0,n-1){
		if(s[o]=='(')S.push(o);
		else match[S.top()]=o,match[o]=S.top(),S.pop();
	}
	dfs(0,n-1);
	int ans=0;
	fup(i,0,2){
		fup(j,0,2){
			(ans+=dp[0][n-1][i][j])%=mod;
		}
	}
	cout<<ans<<endl;
}
posted @ 2023-03-12 00:34  liangqianxing  阅读(22)  评论(0)    收藏  举报