首页 > 其他分享 >题解 Coloring Brackets

题解 Coloring Brackets

时间:2023-10-03 23:03:42浏览次数:51  
标签:p2 Coloring Brackets 题解 括号 p1 dp && match

题目链接

对于括号问题,考虑区间 \(dp\)。这道题的括号序列是固定的,所以直接找出每个括号对应的括号在进行转化即可。

设 \(f_{l,r,0/1/2,0/1/2}\) 表示 \(l\sim r\),左括号不染色/染红色/染蓝色,右括号不染色/染红色/染蓝色的方案数。

若 \(l,r\) 是一对匹配括号,那么f_{l,r} 便可以由 \(f_{l+1,r-1}\) 转移得来,注意相邻括号颜色不同。

接着进行中间的拆分,注意括号问题不能直接枚举断点 \(k\) 拆分,这样会将 \(()()()\) 分别拆成 \((),()()\) 和 \(()(),()\) 计算两次。所以强行规定第一个拆分的一定是左右括号匹配好的,后面一段不管,也就是将 \([l,r]\) 拆成 \([l,match_l]\) 和 \(match_l+1,r\) 两个区间进行计算,同样注意相邻括号颜色不能相同。

由于很大程度根据括号匹配情况进行 \(dp\),所以这里采取记忆话搜索进行 \(dp\)。

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
#define PII pair<int,int>
LL read() {
	LL sum=0,flag=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
	while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
	return sum*flag;
}

const int N=710;
const LL MOD=1e9+7;
int n; string s;
int match[N];
LL f[N][N][3][3];

int pd(int l,int r) {
	if(s[l]=='('&&s[r]==')') return 1;
	else return 0;
}

LL dfs(int l,int r,int p1,int p2) {
	if(l>r) return 0;
	if((r-l+1)%2!=0) return 0;
	if(f[l][r][p1][p2]!=-1) return f[l][r][p1][p2];
	f[l][r][p1][p2]=0;
	if(match[l]==r) {
		if((p1&&!p2)||(!p1&&p2)) {
			for(int x1=0;x1<=2;x1++) {
				for(int x2=0;x2<=2;x2++){
					if((p1==x1&&x1)||(p2==x2&&x2)) continue;
					f[l][r][p1][p2]=(f[l][r][p1][p2]+dfs(l+1,r-1,x1,x2))%MOD;
				}
			}			
		}
	}
	for(int x1=0;x1<=2;x1++) {
		for(int x2=0;x2<=2;x2++){
			if(x1==x2&&x1) continue;
			f[l][r][p1][p2]=(f[l][r][p1][p2]+dfs(l,match[l],p1,x1)*dfs(match[l]+1,r,x2,p2))%MOD;
		}
	}
	
	return f[l][r][p1][p2];
}

int main() {
	cin>>s;
	n=s.size(); s=" "+s;
	stack<int> st;
	memset(f,-1,sizeof(f));
	for(int i=1;i<=n;i++) {
		if(st.size()&&s[st.top()]=='('&&s[i]==')') {
			match[st.top()]=i; match[i]=st.top(); st.pop();
		}
		else st.push(i);
	}
	for(int i=1;i<=n-1;i++) {
		if(pd(i,i+1)) {
			f[i][i+1][0][1]=f[i][i+1][0][2]=f[i][i+1][1][0]=f[i][i+1][2][0]=1;
		}
	}
	LL ans=0;
	for(int i=0;i<=2;i++) {
		for(int j=0;j<=2;j++) {
			ans=(ans+dfs(1,n,i,j))%MOD;
		}
	}
	cout<<ans<<endl;


	return 0;
}

标签:p2,Coloring,Brackets,题解,括号,p1,dp,&&,match
From: https://www.cnblogs.com/zhangyuzhe/p/17741777.html

相关文章

  • CF1661D Progressions Covering 题解
    最详细的题解题目传送门:ProgressionsCovering阅读前人题解时,限于个人能力有限,有一些地方想了好一会儿才懂。发现很多题解都是在@SDLTF_凌亭风等作者基础上延伸,但详细程度依旧有限,尽管这篇题解亦是站在他们基础上延伸的,这篇题解更为详细的点明了很多地方。本人第一次写题解,......
  • 洛谷 Power Tree 题解
    题目链接PowerTree分析将叶子节点按dfs序重标号后,每次控制操作可以转化为将子树内叶子节点所在区间加(或减)一个数不难可以想到将叶子区间进行差分每次对\(l\)到\(r\)的操作可以转化为将\(l\)上的数转移到\(r+1\)上每次操作后差分数组的和不变将所有点权变为\(0\)......
  • [题解] CF632F - Swimmers in the Pool
    CF632F-SwimmersinthePool题目传送门题意给定一个大小为\(n\timesn\)的矩阵\(A\)。假设\(A\)满足以下条件,那么称该矩阵为MAGIC,否则为NOTMAGIC,并输出对应的属性(即\(A\)是MAGIC还是NOTMAGIC)。$A_{i,j}=A_{j,i}$;$A_{i,i}=0$;$A_{i,j}\le......
  • GDCPC2023 B , D , F , K 题解
    和队友一起打的2023年广东省大学生程序设计竞赛重现赛,写了B,D,K,胡了一个F。D题目大意随着广东的建设与发展,越来越多人选择来到广东开始新生活。在一片新建的小区,有\(n\)个人要搬进\(m\)栋排成一行的房子,房子的编号从\(1\)到\(m\)(含两端)。房子\(u\)和\(v\)相邻......
  • 题解 [CSP-S 2021] 括号序列
    题目链接对于括号题,基本是栈匹配没有匹配的左括号和区间\(dp\)两个方向。这道题括号序列并不确定,只能用区间\(dp\)搞。如果直接设\(f_{l,r}\)表示\(l\simr\)的合法括号序列,那么由区间\(dp\)的套路可知,需要枚举中间点进行合并,那么\(()()()\)的情况就会出问题,原因是......
  • 【UVA 12100】Printer Queue 题解(队列+优先队列)
    计算机科学学生会中唯一的打印机正经历着极其繁重的工作量。有时,打印机队列中有100个作业,您可能需要等待数小时才能获得一页输出。由于某些作业比其他作业更重要,黑客将军为打印作业队列发明并实现了一个简单的优先级系统。现在,为每个作业分配1到9之间的优先级(9是最高优先级,1是最低......
  • [题解]CF1748C Zero-Sum Prefixes
    UPD23.10.3更新的对思路的描述,以及代码。思路对于每一个\(a_i=0\),如果我们将它变为\(x\),都可以直接将\(i\simn\)位置上的前缀和加\(x\)。设\(a_j\)是\(a_i\)后第一个\(0\),那么,在\(j\)时同样有上述规律。所以,我们只需在\(i\)时考虑,\(i\sim(j-1)\)的贡......
  • 题解 [蓝桥杯 2016 省 B] 交换瓶子
    题目链接本题解讲解环图的做法。要将一个\(1\simn\)的排列通过交换变成\(1\simn\),可以先将\(i\)向\(a_i\)连边,那么最终一定会练成若干个环(每个点只有一个出度,也只有一个入度)。假设交换在同一个环中的节点,一个环显然会变成两个环,也就是说,交换一次最多增加一个环的数量,......
  • 【题解】洛谷 P1003 [NOIP2011 提高组] 铺地毯
    原题链接解题思路如果直接按照题意开一个二维数组来模拟每个点最上面的地毯编号,会发现所占空间最坏情况下约为(2*105)2*4B=4*1010*4B=1.6*1011B≈149GB,程序完全无法运行。但实际上没有必要将每一个点的信息记录下来,只需要记录每一块地毯能覆盖哪些点,再依次判断哪那些地毯可以......
  • 「题解」Codeforces Round 894 (Div. 3)
    A.GiftCarpetProblem题目Sol&Code签到题#include<bits/stdc++.h>#defineN21typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT,n,m,a[4];std::strings[N];i......