题目链接:

http://codeforces.com/problemset/problem/149/D

D. Coloring Brackets

time limit per test2 seconds
memory limit per test256 megabytes
#### 问题描述
> 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).
#### 输入
> The first line contains the single string s (2 ≤ |s| ≤ 700) which represents a correct bracket sequence.
#### 输出
> Print the only number — the number of ways to color the bracket sequence that meet the above given conditions modulo 1000000007 (109 + 7).
####样例输入
> (()())
####样例输出
> 40
## 题意
> 每对括号必须满足一边染成红色或蓝色,另一边不染色,且相邻的两个括号颜色不同。

题解

之前的一种思路是dp[l][r][s1][s2]代表最左边的括号的状态为s1,s2但是,这种是错的额!因为你看不到r右边的限制了!!!!

贴个错误代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=777;
const int mod=1e9+7; LL dp[maxn][maxn][3][3];
char str[maxn];
int rig[maxn];
int n; LL dfs(int l,int r,int s1,int s2) {
if(l>=r) return 0;
if(l+1==r&&(s1==0&&s2>0||s1>0||s2==0)) return 1;
if(dp[l][r][s1][s2]>=0) return dp[l][r][s1][s2]; LL &res=dp[l][r][s1][s2]=0; int ll=l,rr=rig[l]; LL cntl=0,cntr=0;
if(s1==0) {
if(ll+1<rr-1) {
cntl+=dfs(ll+1,rr-1,1,0);
cntl+=dfs(ll+1,rr-1,2,0);
cntl+=dfs(ll+1,rr-1,0,3-s2);
} else {
cntl=1;
}
cntl%=mod; if(rr+1>r) {
cntr=1;
} else {
cntr+=dfs(rr+1,r,0,1);
cntr+=dfs(rr+1,r,0,2);
cntr+=dfs(rr+1,r,3-s2,0);
}
cntr%=mod; res+=cntl*cntr;
res%=mod;
} else {
if(ll+1<rr-1) {
cntl+=dfs(ll+1,rr-1,3-s1,0);
cntl+=dfs(ll+1,rr-1,0,1);
cntl+=dfs(ll+1,rr-1,0,2);
} else {
cntl=1;
}
cntl%=mod; if(rr+1>r) {
cntr=1;
} else {
cntr+=dfs(rr+1,r,0,1);
cntr+=dfs(rr+1,r,0,2);
cntr+=dfs(rr+1,r,1,0);
cntr+=dfs(rr+1,r,2,0);
}
cntr%=mod; res+=cntl*cntr;
res%=mod;
} return res;
} int main() {
scf("%s",str+1);
n=strlen(str+1);
stack<int> mst;
clr(dp,-1);
clr(rig,-1);
for(int i=1; i<=n; i++) {
if(str[i]==')') {
rig[mst.top()]=i;
mst.pop();
} else {
mst.push(i);
}
}
// for(int i=1;i<=n;i++){
// prf("(%d,%d)\n",i,rig[i]);
// } LL ans=dfs(1,n,0,1)+dfs(1,n,0,2)+dfs(1,n,1,0)+dfs(1,n,2,0);
bug(dp[1][n][0][1]);
bug(dp[1][n][0][2]);
bug(dp[1][n][1][0]);
bug(dp[1][n][2][0]); bug(dp[2][5][2][0]); prf("%I64d\n",ans); return 0;
} //end----------------------------------------------------------------------- /*
(()())
*/

正确的表示应该是dp[l][r][s1][s2]代表l左边和r右边的限制!!!

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=777;
const int mod=1e9+7; LL dp[maxn][maxn][3][3];
char str[maxn];
int rig[maxn];
int n; LL dfs(int l,int r,int s1,int s2) {
if(l>r) return 1;
if(dp[l][r][s1][s2]>=0) return dp[l][r][s1][s2]; LL &res=dp[l][r][s1][s2]=0;
int ll=l,rr=rig[l];
if(rr==r){
if(s1==0){
if(s2==0){
res+=dfs(ll+1,rr-1,0,1);
res+=dfs(ll+1,rr-1,0,2);
res+=dfs(ll+1,rr-1,1,0);
res+=dfs(ll+1,rr-1,2,0);
res%=mod;
}else{
res+=dfs(ll+1,rr-1,0,3-s2);
res+=dfs(ll+1,rr-1,1,0);
res+=dfs(ll+1,rr-1,2,0);
res%=mod;
}
}else{
if(s2==0){
res+=dfs(ll+1,rr-1,0,1);
res+=dfs(ll+1,rr-1,0,2);
res+=dfs(ll+1,rr-1,3-s1,0);
res%=mod;
}else{
res+=dfs(ll+1,rr-1,0,3-s2);
res+=dfs(ll+1,rr-1,3-s1,0);
res%=mod;
}
}
}else{
if(s1==0){
res=(res+dfs(ll+1,rr-1,0,1)*dfs(rr+1,r,1,s2)%mod)%mod;
res=(res+dfs(ll+1,rr-1,0,2)*dfs(rr+1,r,2,s2)%mod)%mod;
res=(res+dfs(ll+1,rr-1,1,0)*dfs(rr+1,r,0,s2)%mod)%mod;
res=(res+dfs(ll+1,rr-1,2,0)*dfs(rr+1,r,0,s2)%mod)%mod;
}else{
res=(res+dfs(ll+1,rr-1,0,1)*dfs(rr+1,r,1,s2)%mod)%mod;
res=(res+dfs(ll+1,rr-1,0,2)*dfs(rr+1,r,2,s2)%mod)%mod;
res=(res+dfs(ll+1,rr-1,3-s1,0)*dfs(rr+1,r,0,s2)%mod)%mod;
}
} return res;
} int main() {
scf("%s",str+1);
n=strlen(str+1);
stack<int> mst;
clr(dp,-1);
clr(rig,-1);
for(int i=1; i<=n; i++) {
if(str[i]==')') {
rig[mst.top()]=i;
mst.pop();
} else {
mst.push(i);
}
} LL ans=dfs(1,n,0,0);
prf("%I64d\n",ans); return 0;
} //end----------------------------------------------------------------------- /*
(()())
*/

短一点的代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=777;
const int mod=1e9+7; LL dp[maxn][maxn][3][3];
char str[maxn];
int rig[maxn];
int n; LL dfs(int l,int r,int s1,int s2) {
if(l>r) return 1;
if(dp[l][r][s1][s2]>=0) return dp[l][r][s1][s2]; LL &res=dp[l][r][s1][s2]=0;
int ll=l,rr=rig[l];
for(int i=1;i<=2;i++){
//left
if(i!=s1) res=(res+dfs(ll+1,rr-1,i,0)*dfs(rr+1,r,0,s2)%mod)%mod;
//right
if(rr<r||i!=s2) res=(res+dfs(ll+1,rr-1,0,i)*dfs(rr+1,r,i,s2)%mod)%mod;
} return res;
} int main() {
scf("%s",str+1);
n=strlen(str+1);
stack<int> mst;
clr(dp,-1);
clr(rig,-1);
for(int i=1; i<=n; i++) {
if(str[i]==')') {
rig[mst.top()]=i;
mst.pop();
} else {
mst.push(i);
}
} LL ans=dfs(1,n,0,0);
prf("%I64d\n",ans); return 0;
} //end----------------------------------------------------------------------- /*
(()())
*/

Codeforces Round #106 (Div. 2) D. Coloring Brackets 区间dp的更多相关文章

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

  2. Codeforces Round #369 (Div. 2) C. Coloring Trees(dp)

    Coloring Trees Problem Description: ZS the Coder and Chris the Baboon has arrived at Udayland! They ...

  3. Codeforces Round #369 (Div. 2) C. Coloring Trees (DP)

    C. Coloring Trees time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  4. Codeforces Round #369 (Div. 2) C. Coloring Trees(简单dp)

    题目:https://codeforces.com/problemset/problem/711/C 题意:给你n,m,k,代表n个数的序列,有m种颜色可以涂,0代表未涂颜色,其他代表已经涂好了,连着 ...

  5. Codeforces Round #336 (Div. 2) D. Zuma(区间DP)

    题目链接:https://codeforces.com/contest/608/problem/D 题意:给出n个宝石的颜色ci,现在有一个操作,就是子串的颜色是回文串的区间可以通过一次操作消去,问最 ...

  6. Codeforces Round #367 (Div. 2) C. Hard problem(DP)

    Hard problem 题目链接: http://codeforces.com/contest/706/problem/C Description Vasiliy is fond of solvin ...

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

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

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

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

  9. codeforce 149D Coloring Brackets 区间DP

    题目链接:http://codeforces.com/problemset/problem/149/D 继续区间DP啊.... 思路: 定义dp[l][r][c1][c2]表示对于区间(l,r)来说, ...

随机推荐

  1. 腾讯云Mac图床插件

    背景 随着博客越写越多,难免会遇到需要插入图片来说明的情况. 图床选择 首先调研了市面上的图床服务,本着稳定长期的目标,过滤掉了打一枪换一个地方的野鸡小网站,剩余比较靠谱的优缺点如下. 图床 优点 缺 ...

  2. vue实现首页导航切换不同路由的方式

    vue实现切换首页路由导航 ,根据切换的不同导航跳转不同的路由,以及当前选中的导航添加选中样式.  html代码: <nav> <!-- 导航栏 --> <div cla ...

  3. 目标反射回波检测算法及其FPGA实现 之二:互相关/卷积/FIR电路的实现

    目标反射回波检测算法及其FPGA实现之二: 互相关/卷积/FIR电路的实现 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激 ...

  4. 20155301 滕树晨linux基础——linux进程间通信(IPC)机制总结

    20155301 滕树晨linux基础--linux进程间通信(IPC)机制总结 共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在 ...

  5. .net core的定时任务框架Timed Job

    参考文档:http://www.1234.sh/post/pomelo-extensions-timed-jobs 在该文档中介绍了怎么使用timed job,但是在使用db的时候会发生错误,错误一般 ...

  6. AtCoder ExaWizards 2019 D Modulo Operations

    题意 给出一个长度为\(n\)的数列和数字\(X\),对于数列的每一种排列,其权值\(X\)依次对排列中的数取模,求出\(n!\)种情况最后剩下的数的权值和 分析 如果大的数字排在小的数字后面,那么大 ...

  7. Kafka系列四 flume-kafka-storm整合

    flume-kafka-storm flume读取日志数据,然后发送至kafka. 1.flume配置文件 agent.sources = kafkaSource agent.channels = k ...

  8. python实战——教你用微信每天给女朋友说晚安

    但凡一件事,稍微有些重复.我就考虑怎么样用程序来实现它. 这里给各位程序员朋友分享如何每天给朋友定时微信发送”晚安“,故事,新闻,等等··· ··· 最好运行在服务器上,这样后台挂起来更方便. 准备 ...

  9. java多线程系列(一)---多线程技能

    java多线程技能 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  10. vs2012 与 win7 不兼容的问题

    Visual Studio 2012 与此版本的 Windows 不兼容 突然出现的,如下图: 这个是网上找的图,我的没来得及截图就修复了,基本一致,只是我的是win7 64位系统,所以安装位置那里是 ...