CF149D Coloring Brackets
CF149D Coloring Brackets
题面:
给出一个配对的括号序列(如"\((())()\)"、"\(()\)"等, "\()()\)"、"\((()\)"是不符合要求的 ),对该序列按以下方法进行染色:
- 1.一个括号可以染红色、蓝色或不染色
- 2.一对匹配的括号需要且只能将其中一个染色
- 3.相邻两个括号颜色不能相同(但可以都不染色) 求符合条件的染色方案数(对1000000007取模)
输入:一行,表示括号序列
输出:一个数表示方案数(对1000000007取模) 数据范围:
这道题转移很恶心,并且也比较难想。是一道很仙的区间 \(dp\) 题。
想了半天,发现只会打爆搜,最后看了看题解 才把这题搞懂
按照区间dp的套路我们还是设 \(f[l][r]\) 表示从 \(l\) 刷到 \(r\) 的合法方案数。
这是,我们还要填上一维颜色,因为限制是和颜色相关的。
\(f[l][r][0,1,2][0,1,2]\) 表示从\(l\) 刷到 \(r\) 且 \(l\) 不涂/涂红色/涂蓝色, \(r\) 不涂/涂红色/涂蓝色的方案数。
边界 \(l +1 == r\):
\(l\) 和 \(r\) 不配对,就是这种情况 \("(("\) ,就要保证 \(l\) 和 \(r\) 的颜色不同就行,还要算上他们两个都不涂的情况。
if(match[l] != r) f[l][r][0][0] = f[l][r][0][1] = f[l][r][0][2] = f[l][r][1][0] = f[l][r][2][0] = 1
\(l\) 和 \(r\) 配对的情况,就不能算 两个都不涂的情况
if(match[l] == r) f[l][r][0][1] = f[l][r][0][2] = f[l][r][1][0] = f[l][r][2][0] = 1
转移的时候:
\(l\) 和 \(r\) 匹配的时候,也就是 \("(....)"\) 的情况
我们就只需要考虑 \(l\) 和 \(l+1\) 以及 \(r-1\) 和 \(r\) 颜色不相同的情况,大力枚举 \(l+1\) 和 \(r\) 的颜色就行。
至于为什么不枚举 \(l\) 和 \(r\) 的颜色,因为那样写太复杂了,你完全可以只考虑 \(l\) 和 \(r\) 的颜色符合限制的方案数。
至于其他 \(l\) 和 \(r\) 的颜色情况都不符合条件,可以直接赋为 \(0\)
Code
for(int i = 0; i <= 2; i++)//l+1的颜色
{
for(int j = 0; j <= 2; j++)//r-1的颜色
{//注意相邻的颜色不能相同,也就是不能发生转移
if(j != 1) f[l][r][0][1] = (f[l][r][0][1] + f[l+1][r-1][i][j]) % p;
if(j != 2) f[l][r][0][2] = (f[l][r][0][2] + f[l+1][r-1][i][j]) % p;
if(i != 1) f[l][r][1][0] = (f[l][r][1][0] + f[l+1][r-1][i][j]) % p;
if(i != 2) f[l][r][2][0] = (f[l][r][2][0] + f[l+1][r-1][i][j]) % p;
}
}
\(l\) 和 \(r\) 不匹配的时候,也就是\("()()"\) 的情况
这个我们把它分为两个小区间 \(l -> match[l]\) 以及 \({match[l]+1} -> r\)
就可以递归求解了,至于为什么要分成这两个小区间。
因为你分成别的区间的话,要考虑的情况比较多,你要考虑 与 \(l\) 相邻的情况以及和他 匹配的那个括号的情况。
这样就可以少讨论与 \(l\) 相邻的情况,只需要考虑 \(match[l]\) 与 \(match[l]+1\) 相邻的情况。
然后大力枚举一下这四个点的颜色就可以了,只不过写起来有点费劲
Code
for(int i = 0; i <= 2; i++)//l的颜色
{
for(int j = 0; j <= 2; j++)//r的颜色
{
for(int k = 0; k <= 2; k++)//match[l] 的颜色
{
for(int u = 0; u <= 2; u++)//match[l+1] 的颜色
{
if(k == u && k != 0 && u != 0) continue;//相邻的颜色不能相同,但可以都不染色
f[l][r][i][j] = (f[l][r][i][j] + f[l][match[l]][i][k] * f[match[l]+1][r][j][u] % p) % p;
}
}
}
}
至于这个循环考虑了 \(l\) 和 \(match[l]\) 都不涂的情况,但那种情况的方案数为 \(0\) ,在乘另一个数对答案没有贡献。
最后的答案就是 \(\displaystyle \sum_{i=0}^2 \sum_{j=0}^{2} f[1][n][i][j]\)。 枚举一下起点和终点的颜色就可以了。
Code(我写的是记忆化搜索的放法)
当然了,你也可以写平常的那种写法。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
const int p = 1e9+7;
char s[710];
int n,top,ans;
int sta[710],match[710],f[710][710][3][3];
void slove(int l,int r)
{
if(l+1 == r)
{
if(match[l] != r) f[l][r][0][0] = 1;
f[l][r][0][1] = f[l][r][0][2] = f[l][r][1][0] = f[l][r][2][0] = 1;
return;
}
if(match[l] == r)//()
{
slove(l+1,r-1);
for(int i = 0; i <= 2; i++)//l+1的颜色
{
for(int j = 0; j <= 2; j++)//r-1的颜色
{
if(j != 1) f[l][r][0][1] = (f[l][r][0][1] + f[l+1][r-1][i][j]) % p;
if(j != 2) f[l][r][0][2] = (f[l][r][0][2] + f[l+1][r-1][i][j]) % p;
if(i != 1) f[l][r][1][0] = (f[l][r][1][0] + f[l+1][r-1][i][j]) % p;
if(i != 2) f[l][r][2][0] = (f[l][r][2][0] + f[l+1][r-1][i][j]) % p;
}
}
}
else//()....()
{
slove(l,match[l]); slove(match[l]+1,r);
for(int i = 0; i <= 2; i++)//l的颜色
{
for(int j = 0; j <= 2; j++)//r的颜色
{
for(int k = 0; k <= 2; k++)//match[l] 的颜色
{
for(int u = 0; u <= 2; u++)//match[l+1] 的颜色
{
if(k == u && k != 0 && u != 0) continue;//相邻的颜色不能相同,但可以都不染色
f[l][r][i][j] = (f[l][r][i][j] + f[l][match[l]][i][k] * f[match[l]+1][r][j][u] % p) % p;
}
}
}
}
}
}
signed main()
{
scanf("%s",s+1);
n = strlen(s+1);
for(int i = 1; i <= n; i++)
{
if(s[i] == '(')
{
sta[++top] = i;
}
else if(s[i] == ')')
{
int t = sta[top--];
match[t] = i;
match[i] = t;
}
}
slove(1,n);
for(int i = 0; i <= 2; i++)
{
for(int j = 0; j <= 2; j++)
{
ans = (ans + f[1][n][i][j]) % p;;
}
}
printf("%lld\n",ans);
return 0;
}
CF149D Coloring Brackets的更多相关文章
- CF149D. Coloring Brackets[区间DP !]
题意:给括号匹配涂色,红色蓝色或不涂,要求见原题,求方案数 区间DP 用栈先处理匹配 f[i][j][0/1/2][0/1/2]表示i到ji涂色和j涂色的方案数 l和r匹配的话,转移到(l+1,r-1 ...
- CodeForces 149D Coloring Brackets
Coloring Brackets time limit per test: 2 seconds memory limit per test: 256 megabytes input: standar ...
- Codeforces Round #106 (Div. 2) D. Coloring Brackets 区间dp
题目链接: http://codeforces.com/problemset/problem/149/D D. Coloring Brackets time limit per test2 secon ...
- Codeforces 149D Coloring Brackets(树型DP)
题目链接 Coloring Brackets 考虑树型DP.(我参考了Q巨的代码还是略不理解……) 首先在序列的最外面加一对括号.预处理出DFS树. 每个点有9中状态.假设0位不涂色,1为涂红色,2为 ...
- Codeforces Round #106 (Div. 2) D. Coloring Brackets —— 区间DP
题目链接:https://vjudge.net/problem/CodeForces-149D D. Coloring Brackets time limit per test 2 seconds m ...
- codeforces 149D Coloring Brackets (区间DP + dfs)
题目链接: codeforces 149D Coloring Brackets 题目描述: 给一个合法的括号串,然后问这串括号有多少种涂色方案,当然啦!涂色是有限制的. 1,每个括号只有三种选择:涂红 ...
- CF 149D Coloring Brackets(区间DP,好题,给配对的括号上色,求上色方案数,限制条件多,dp四维)
1.http://codeforces.com/problemset/problem/149/D 2.题目大意 给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色, ...
- Coloring Brackets (区间DP)
Once Petya read a problem about a bracket sequence. He gave it much thought but didn't find a soluti ...
- CF 149D Coloring Brackets 区间dp ****
给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色,上蓝色 2.每对括号必须只能给其中的一个上色 3.相邻的两个不能上同色,可以都不上色 求0-len-1这一区间内 ...
随机推荐
- 使用Unity的50个建议
关于这些建议 这些建议并不适用于所有的项目 这些建议是基于我与3-20人的小团队项目经验总结出来的 结构.可重复使用性.明晰度都是有价的——团队规模和项目规模决定了是否值得付这个价. 一些建议也许公然 ...
- Spine应用--使用Spine动画制作动作游戏
在前面的文章中,已经陆陆续续的讲解了一些使用Spine动画的细节,有了这些细节,我们已经满足了在unity中使用Spine动画制作动作游戏的技术基础. 那么,要使用Spine动画在unity中制作一款 ...
- Django:给requests发送请求功能 套一层衣服。
个人的疑问
- 小花梨判连通 (bfs+思维+map统计数量)
如果两个集合存储颜色的情况相同,说明这两个在k个图中都是在一个集合的 学到的点:用map,将vector映射一个整数时,只有vector后面的邻接的数据都一样时,才认为两个vector一样 代码: # ...
- java-对象引用和对象本身
示意图 应用场景 1.赋值 只有用新的对象本身直接赋值给对应引用,该对象引用的值会改变,因为对象引用指向的对象本身改变了. 2.方法入参 调用方法和被调用方法. 代码 import com.aliba ...
- Java8 Functional(函数式接口)
Functional 函数式(Functional)接口 只包含一个抽象方法的接口,称为函数式接口. 你可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常(即 ...
- H5简单内容
1.简单认识H5 HTML5不仅仅是作为HTML标记语言的一个最新版本,更重要的是它指定了Web开发的一系列标准,成为第一个将Web作为应用开发平台的HTML语言. 我们日常讨论的H5其实是有一个泛称 ...
- 获取.properties配置文件属性值
public class TestProperties { /** * * @Title: printAllProperty * @Description: 输出所有配置信息 * @param pro ...
- js拖拽原理及简单实现(渣渣自学)
第一步 首先简单分析下需求吧,我们就是想实现鼠标拖拽带颜色的方块时,让方块停留在鼠标松开的位置,需要计算的就是拖拽前的坐标和拖拽后的坐标,鼠标移动后相对于原位置的偏移量=目标元素的偏移量,根据这个等式 ...
- oracle之DML和DDL语句的其他用法
DML和DDL语句的其他用法 17.1 DML语句-MERGE 作用:把数据从一个表复制到另一个表,插入新数据或替换掉老数据. Oracle 10g中MERGE有如下一些改进: 1.UPDATE或IN ...