CF149D Coloring Brackets

前言

【题目传送门】
并不是很难的一道题,但仍有值得学习之处。

题解

区间 DP 显然能看出。
而且对于配对的两个括号,肯定是要一起处理。
所以预处理每个括号配对的位置也能想到。
也能想到根据两个端点是否配对,分类讨论加法和乘法。

我遇到的问题

  • 原本设计的 DP 没有只记录了左右括号分别涂某种颜色的情况,这样的话如果区间左右括号不配对就没办法转移了。
  • 想写记搜,但是想到 solve 函数里面还要传入 (op),就不知道该返回什么了。(其实是我 sb 了,如果分情况返回值应该也是可以写的,只不过就略微冗杂了一点,这充分说明我很菜)
  • 分类讨论的时候还有个判断写错了。

正解的思路

  • 记录 (dp(l,r,i,j)) 表示区间内左右端点不涂色/红色/蓝色的方案数。
  • 貌似只能写搜索,因为要保证配对的括号在同一区间。
  • 分情况转移两端是否配对的情况。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define FCC fclose(stdin),fclose(stdout)
const int INF = 0x3f3f3f3f,mod = 1e9+7,N = 706;
inline ll read()
{
	ll ret=0;char ch=' ',c=getchar();
	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
	return ch=='-'?-ret:ret;
}
ll dp[N][N][3][3];
int n,rit[N];
int stk[N],top;
char s[N];
inline ll Mod(ll x,ll y)
{
	return ((x+y)%mod+mod)%mod;
}
void solve(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;
		return;
	}
	if(rit[l]==r)
	{
		solve(l+1,r-1);
		for(int i=0;i<=2;i++)
			for(int j=0;j<=2;j++)
			{
		        if(j!=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;
			}
	}
	else 
	{
		solve(l,rit[l]),solve(rit[l]+1,r);
		for(int i=0;i<=2;i++)	
			for(int j=0;j<=2;j++)
				for(int k=0;k<=2;k++)		
					for(int p=0;p<=2;p++)
					{
					//	if((k==p&&k)||(i==k&&k)||(p==j&&p)) continue;
						if(k==p&&p) continue;
						dp[l][r][i][j]=Mod(dp[l][r][i][j],
						dp[l][rit[l]][i][k]*dp[rit[l]+1][r][p][j]%mod);
					}
	}
}
int main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	for(int i=1;i<=n;i++)	
	{
		if(s[i]=='(') stk[++top]=i;
		else rit[stk[top--]]=i;
	}
	solve(1,n);
	ll ans=0ll;
	for(int i=0;i<=2;i++)	
		for(int j=0;j<=2;j++)	
			ans=(ans+dp[1][n][i][j])%mod;
	printf("%lld
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/conprour/p/15536245.html