刷题杂记之Coloring Brackets

题目传送门

首先看到这个题目,一定要用栈,废话
我们可以发现对于一个括号,不管它是左括号还是右括号,对他有影响的只有3个位置

他的左边括号的颜色
他的右边括号的颜色
他的对应的括号的颜色

对于1,2两个问题,可以利用普通的dp枚举,对于第3个问题,处理这个问题的括号,就可以处理把这个问题删掉的这个区间,所以就可以区间dp

f [ l ] [ r ] [ x ] [ y ] 表 示 l f[l][r][x][y]表示l f[l][r][x][y]l~ r 这 个 区 间 , l 的 颜 色 为 x , r 的 颜 色 为 y 的 方 案 数 r这个区间,l的颜色为x,r的颜色为y的方案数 r,lx,ry
m a t c h [ x ] 表 示 x 是 左 括 号 的 时 候 , 它 对 应 的 右 括 号 在 哪 ( 可 以 用 栈 做 ) match[x]表示x是左括号的时候,它对应的右括号在哪(可以用栈做) match[x]x
f [ l ] [ r ] [ x ] [ y ] = Σ i = 0 3 Σ j = 0 3 { f [ l + 1 ] [ r − 1 ] [ i ] [ j ] ( m a t c h [ l ] = r ) f [ l ] [ m a t c h [ l ] ] [ x ] [ i ] ∗ f [ m a t c h [ l ] + 1 ] [ r ] [ y ] [ i ] ( i , j 满 足 相 邻 的 性 质 ) f[l][r][x][y]= \Sigma _{i=0}^3\Sigma _{j=0}^3\begin{cases}f[l+1][r-1][i][j](match[l]=r)\\ f[l][match[l]][x][i]*f[match[l]+1][r][y][i](i,j满足相邻的性质) \end{cases} f[l][r][x][y]=Σi=03Σj=03{f[l+1][r1][i][j](match[l]=r)f[l][match[l]][x][i]f[match[l]+1][r][y][i](i,j)
用记忆化搜索即可(还有一些细节的处理)

#include<bits/stdc++.h>
using namespace std;
const int N=710;
#define Mod 1000000007
#define ll long long
char s[N];int n,match[N];ll ans;
stack<int>sta;ll f[N][N][3][3];
#define res f[l][r][x][y]
ll dfs(int l,int r,int x,int y){
	if(res!=-1)return res;res=0;
	if(l+1==r)return res=((x>0)!=(y>0));
	if(match[l]==r){
		if((x>0)==(y>0))return 0;
		for(int i=0;i<3;i++)
		  for(int j=0;j<3;j++)
		    if((i==0||i!=x)&&(j==0||j!=y))
		      res=(res+dfs(l+1,r-1,i,j))%Mod;
		return res;
	}
	//l~match[l] match[l]+1~r
	for(int i=0;i<3;i++)
	  for(int j=0;j<3;j++)
	    if(i==0&&j==0||i!=j)
	      res=(res+dfs(l,match[l],x,i)*dfs(match[l]+1,r,j,y)%Mod)%Mod;
	return res;
}
int main()
{
	memset(f,-1,sizeof(f));
	scanf("%s",s+1);ll ans=0;
	int n=strlen(s+1);
	for(int i=1;i<=n;i++)
	  if(s[i]=='(')sta.push(i);
	    else match[sta.top()]=i,sta.pop();
	for(int i=0;i<3;i++)
	  for(int j=0;j<3;j++)
	    ans=(ans+dfs(1,n,i,j))%Mod;
	printf("%lld",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值