【CF 149D】Coloring Brackets(dp)

D. Coloring Brackets
time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Once Petya read a problem about a bracket sequence. He gave it much thought but didn’t find a solution. Today you will face it.

You are given string s. It represents a correct bracket sequence. A correct bracket sequence is the sequence of opening (“(“) and closing (“)“) brackets, such that it is possible to obtain a correct mathematical expression from it, inserting numbers and operators between the brackets. For example, such sequences as “(())()” and “()” are correct bracket sequences and such sequences as “)()” and “(()” are not.

In a correct bracket sequence each bracket corresponds to the matching bracket (an opening bracket corresponds to the matching closing bracket and vice versa). For example, in a bracket sequence shown of the figure below, the third bracket corresponds to the matching sixth one and the fifth bracket corresponds to the fourth one.

You are allowed to color some brackets in the bracket sequence so as all three conditions are fulfilled:

  • Each bracket is either not colored any color, or is colored red, or is colored blue.
  • For any pair of matching brackets exactly one of them is colored. In other words, for any bracket the following is true: either it or the matching bracket that corresponds to it is colored.
  • No two neighboring colored brackets have the same color.

Find the number of different ways to color the bracket sequence. The ways should meet the above-given conditions. Two ways of coloring are considered different if they differ in the color of at least one bracket. As the result can be quite large, print it modulo 1000000007 (109 + 7).

Input

The first line contains the single string s (2 ≤ |s| ≤ 700) which represents a correct bracket sequence.

Output

Print the only number — the number of ways to color the bracket sequence that meet the above given conditions modulo 1000000007 (109 + 7).

Examples
Input
(())

Output
12

Input
(()())

Output
40

Input
()

Output
4

Note

Let’s consider the first sample test. The bracket sequence from the sample can be colored, for example, as is shown on two figures below.

The two ways of coloring shown below are incorrect.

题目大意:
给出一个的括号序列。保证序列中括号两辆匹配,并且唯一匹配。

有红蓝绿三种涂料,现要给括号染色,要求每对括号中有且只有一个括号被染色,任意相邻括号颜色不可相同,无色除外。

误打误撞走上正轨……
开始想的是dp,普通的遍历dp。
后来想用之前做括号匹配的方式,进栈出栈搞一下。
最后想到用搜索,递归的时候处理。

真是开始的思路影响很大啊,要是照着前两种想法,应该会在歧途上越走越远……

搜索的初步思路是,每找到一对括号时,以其左右边界为新边界,搜索括号内包含的括号。
那么搜索出什么可以让递归变得有意义呢?
对于当前边界,或者说对于括号[L,R]而言,可涂色的方案有2*3种,左涂三种颜色和右涂三种颜色。
相邻括号颜色不能相同,导致方案数受其内包含括号,以及其左右括号影响。

现不考虑左右相邻括号。其内包含括号可能有多个,类似 (()()) (()())这种情况
而对于最外层括号2*3种情况的合法性,由且仅由内部最左和最右括号颜色的选择有关。可知有3*3种选择。

这样问题就进一步细化了,以外层括号为边界时,想要搜索到的答案其实就是内部最左最右两个括号3*3种组合各自的方案数。

如果内部包含的只有一个括号,类似 (()) (())这种,或者 ((()())) ((()()))这种也算,因为我们在乎的只是当前层的下一层,其余的归下一层管。内部的组合就是通过搜索返回的东西。

如果是多个括号,类似 (()()) (()()),那么 dp[dep][i][j] dp[dep][i][j]定义为dep层,最左括号为i色,最右括号为j色的方案数,这里用到类似转移的方法,当在当前层找到新括号时,搜索出这个括号2*3种涂色的方案数,然后与这个dp数组组合出来,更新到其中即可。

另外需要注意的是,这里求出的是当前层内部左右颜色组合的方案数,当要返回时,需要转换到上一层,也就是要把当前层3*2涂色的方案数求出。

最顶层注意不需转换,因为边界的两个括号是虚加上的

代码略拖拉略搓。。。慎看

#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;char str[777];
LL dp[777][3][3];
LL tmp[3][3];void dfs(int l,int r,int dep)
{//初始化当前层左右边界涂色方案for(int i = 0; i < 3; ++i)for(int j = 0; j < 3; ++j)dp[dep][i][j] = ((i && j) || (i == 0 && j == 0))? 0: 1;//内部没有多余括号if(l >= r-1) return;int st = l+1;//左括号位置int ph = 0;//用来匹配完整括号 左括号++ 右括号-- 当变为0说明出现当前层+1层的括号匹配bool q = 0;//当前层内部是否遍历过括号for(int i = l+1; i < r; ++i){if(str[i] == '(') ph++;else ph--;if(i != l+1 && (i == r || str[i] == ')') && ph == 0){dfs(st,i,dep+1);st = i+1;if(q == 0)//边界内部出现的第一个完整匹配{for(int j = 0; j < 3; ++j)for(int k = 0; k < 3; ++k)dp[dep][j][k] = dp[dep+1][j][k];}else{for(int j = 0; j < 3; ++j)for(int k = 0; k < 3; ++k){tmp[j][k] = dp[dep][j][k];dp[dep][j][k] = 0;}for(int j = 0; j < 3; ++j)for(int k = 0; k < 3; ++k)for(int ll = 0; ll < 3; ++ll)for(int rr = 0; rr < 3; ++rr)if(ll != rr || ll == 0)dp[dep][j][k] = (dp[dep][j][k] + (tmp[j][ll]*dp[dep+1][rr][k])%mod)%mod;}q = 1;}}if(dep)//不是最顶层(边界为真实的括号{for(int i = 0; i < 3; ++i)for(int j = 0; j < 3; ++j){tmp[i][j] = dp[dep][i][j];dp[dep][i][j] = 0;}for(int i = 0; i < 3; ++i)for(int j = 0; j < 3; ++j)if((i == 0) + (j == 0) == 1) for(int ll = 0; ll < 3; ++ll)if(i != ll || i == 0) for(int rr = 0; rr < 3; ++rr)if(j != rr || j == 0) dp[dep][i][j] = (dp[dep][i][j] + tmp[ll][rr])%mod;}}int main()
{//fread("");//fwrite("");scanf("%s",str);dfs(-1,strlen(str),0);LL ans = 0;for(int i = 0; i < 3; ++i)for(int j = 0; j < 3; ++j)ans = (ans+dp[0][i][j])%mod;printf("%lld\n",ans);return 0;
}

【CF 149D】Coloring Brackets(dp)相关推荐

  1. 【CF#706B】 Interesting drink (二分)

    题干: 瓦西里喜欢在努力工作后休息,所以你可能经常在附近的一些酒吧见到他.他喜欢 "Beecola",可以从 n 个不同的商店买到.在第 i 个商店的价格为 xi 元. 瓦西里计划 ...

  2. 【洛谷】P1388 算式(dp)

    题目描述 给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大.因为乘号和加号一共就是N-1个了,所以恰好每两个相邻数字之间都有一个符号.例如: N ...

  3. 【VIJOS - P1037】搭建双塔(dp)

    题干: 描述 2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难.为了纪念"9?11"事件,Mr. F决定自己用水晶来搭建一座双塔. ...

  4. 【HDU - 2089 】不要62 (dp)

    题干: 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).  杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客 ...

  5. 【BZOJ 1222】 [HNOI2001] 产品加工(DP)

    Description 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机 ...

  6. 【luogu CF1693D】Decinc Dividing(DP)

    Decinc Dividing 题目链接:luogu CF1693D 题目大意 给你一个排列,问你有多少个区间满足可以删掉一个单调递减子序列(可以是空的)得到一个单调递增数组. 思路 其实题目就是问你 ...

  7. *【HDU - 5707】Combine String(dp)

    题干: Given three strings aa, bb and cc, your mission is to check whether cc is the combine string of  ...

  8. 【ZOJ - 1163】The Staircases(dp)

    题干: One curious child has a set of N little bricks. From these bricks he builds different staircases ...

  9. 【LOJ 3037】开关游戏(DP)

    开关游戏 题目链接:LOJ 3037 题目大意 给你两个 01 串,分别是初始串和目标串,你可以有三种操作:选择一个区间,把区间里面的都变成 0/1,或者把区间里面的 01 反转. 问你最少要操作多少 ...

最新文章

  1. C语言数组只会输出两个!_只愿与一人十指紧扣_新浪博客
  2. SpringBoot 2.6.0发布:禁止循环依赖,还有哪些实用的更新?
  3. 兑吧:游戏化玩转用户运营的三驾马车
  4. 转 java synchronized详解
  5. 高斯09linux教程,Gaussian 09的安装与使用
  6. 住宅内部通信系统市场现状研究分析与发展前景预测报告
  7. 抖音微博火山快手皮皮虾微视去水印附源码
  8. lzg_ad:XPE常见问题FAQ
  9. 计算机网络辩论赛主持词,辩论赛主持词(精选)
  10. 阿里云对象存储服务OSS前后联调
  11. php 发送邮箱验证怎么做,PHP 实现 注册等的邮箱验证 (二)—— 使用 PHPMailer 发送邮件...
  12. opencv中meanshift和camshift函数的使用
  13. GLSL vs HLSL vs Cg
  14. 优派vx2480功能简评
  15. Windows远程访问服务器jupyter notebook
  16. [OS-Linux]详解Linux的文件系统、inode和动静态库
  17. Hibernate对象与对象的关系
  18. Matlab App Designer 【03】绘制基本测试函数图像以及摸鱼听歌
  19. bim软件功能划分可以分为几类?用于revit的出图插件
  20. JavaWeb基础(2):熟悉HTMLCSS、Servlet、JSP、EL、JSTL、会话控制、jQuery、JSON、Filter、Listener

热门文章

  1. Android Support 包的作用、用法
  2. 将python文件打包成exe文件(带附属txt文件)
  3. Oracle EBS OM Drop Ship Orders(直发业务)测试
  4. 第二十章 SQL谓词 %STARTSWITH(二)
  5. stm32cubemx PWM
  6. 华为产品测评官-开发者之声 半吊子学生的两天体验
  7. Unity 修改Prefab实例将Transform变为RectTransform
  8. 网上赚钱能做什么兼职?空闲时间可做的项目有哪些?
  9. 织梦版权修改dedecms底部版权如何在后台修改去除
  10. 如何成为一名量化工程师?专业猎头建议——几个小tips!