CF149D Coloring Brackets

Link

题面:

给出一个配对的括号序列(如"\((())()\)"、"\(()\)"等, "\()()\)"、"\((()\)"是不符合要求的 ),对该序列按以下方法进行染色:

  • 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的更多相关文章

  1. CF149D. Coloring Brackets[区间DP !]

    题意:给括号匹配涂色,红色蓝色或不涂,要求见原题,求方案数 区间DP 用栈先处理匹配 f[i][j][0/1/2][0/1/2]表示i到ji涂色和j涂色的方案数 l和r匹配的话,转移到(l+1,r-1 ...

  2. CodeForces 149D Coloring Brackets

    Coloring Brackets time limit per test: 2 seconds memory limit per test: 256 megabytes input: standar ...

  3. Codeforces Round #106 (Div. 2) D. Coloring Brackets 区间dp

    题目链接: http://codeforces.com/problemset/problem/149/D D. Coloring Brackets time limit per test2 secon ...

  4. Codeforces 149D Coloring Brackets(树型DP)

    题目链接 Coloring Brackets 考虑树型DP.(我参考了Q巨的代码还是略不理解……) 首先在序列的最外面加一对括号.预处理出DFS树. 每个点有9中状态.假设0位不涂色,1为涂红色,2为 ...

  5. 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 ...

  6. codeforces 149D Coloring Brackets (区间DP + dfs)

    题目链接: codeforces 149D Coloring Brackets 题目描述: 给一个合法的括号串,然后问这串括号有多少种涂色方案,当然啦!涂色是有限制的. 1,每个括号只有三种选择:涂红 ...

  7. CF 149D Coloring Brackets(区间DP,好题,给配对的括号上色,求上色方案数,限制条件多,dp四维)

    1.http://codeforces.com/problemset/problem/149/D 2.题目大意 给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色, ...

  8. Coloring Brackets (区间DP)

    Once Petya read a problem about a bracket sequence. He gave it much thought but didn't find a soluti ...

  9. CF 149D Coloring Brackets 区间dp ****

    给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色,上蓝色 2.每对括号必须只能给其中的一个上色 3.相邻的两个不能上同色,可以都不上色 求0-len-1这一区间内 ...

随机推荐

  1. python爬虫实战---爬取大众点评评论

    python爬虫实战—爬取大众点评评论(加密字体) 1.首先打开一个店铺找到评论 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经 ...

  2. android Studio(3.2.1) NDK配置

    1.创建as工程 2. 创建class类 3. 生成头文件 3.1 配置命令工具 添加工具: 配置工具: Program: $JDKPath$\bin\javah.exe Arugments:-d j ...

  3. eslint prettier vetur eslint

    VScode (版本 1.47.3)安装 eslint prettier vetur 插件 .vue 文件使用 vetur 进行格式化 在文件 .prettierrc 里写 属于你的 pettier ...

  4. OpenvSwitch系列之七 meter表限速

    Open vSwitch系列之一 Open vSwitch诞生 Open vSwitch系列之二 安装指定版本ovs Open vSwitch系列之三 ovs-vsctl命令使用 Open vSwit ...

  5. 20190923-06Linux文件权限类 000 014

    文件属性 Linux系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限.为了保护系统的安全性,Linux系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定.在Linux ...

  6. Java得到指定日期的时间

    //得到指定日期(几天前/几天后)整数往后推,负数往前移动private Date getAppointDay(int num) throws ParseException { DateFormat ...

  7. 企业网站还是要考虑兼容至少IE10

    中国国情,大部分企业还在使用win7,IE浏览器.为了兼容这些,还是少用比较VUE等一些高级的框架,改为使用jquery.用惯了VUE,jquey好多忘得差不多了,其中遇到的问题及解决方案 ajax, ...

  8. 《搭建个人Leanote云笔记本》

    体验实验室简介 阿里云开发者实验室,提供免费阿里云资源,丰富的云计算应用场景, Step by Step 完成云产品的体验 教程介绍 本教程将介绍如何搭建个人Leanote云笔记本. 场景体验 阿里云 ...

  9. 【源码讲解】Spring事务是如何应用到你的业务场景中的?

    初衷 日常开发中经常用到@Transaction注解,那你知道它是怎么应用到你的业务代码中的吗?本篇文章将从以下两个方面阐述Spring事务实现原理: 解析并加载事务配置:本质上是解析xml文件将标签 ...

  10. python操作从数据库中获取数据的接口

    1.输入一个表名,获取表里面的数据 2.判断用户是否存在,如果不存在就添加到数据库里面