Codeforces Round #106 (Div. 2) D. Coloring Brackets 区间dp
题目链接:
http://codeforces.com/problemset/problem/149/D
D. Coloring Brackets
time limit per test2 secondsmemory 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的更多相关文章
- 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 Round #369 (Div. 2) C. Coloring Trees(dp)
Coloring Trees Problem Description: ZS the Coder and Chris the Baboon has arrived at Udayland! They ...
- 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 ...
- Codeforces Round #369 (Div. 2) C. Coloring Trees(简单dp)
题目:https://codeforces.com/problemset/problem/711/C 题意:给你n,m,k,代表n个数的序列,有m种颜色可以涂,0代表未涂颜色,其他代表已经涂好了,连着 ...
- Codeforces Round #336 (Div. 2) D. Zuma(区间DP)
题目链接:https://codeforces.com/contest/608/problem/D 题意:给出n个宝石的颜色ci,现在有一个操作,就是子串的颜色是回文串的区间可以通过一次操作消去,问最 ...
- Codeforces Round #367 (Div. 2) C. Hard problem(DP)
Hard problem 题目链接: http://codeforces.com/contest/706/problem/C Description Vasiliy is fond of solvin ...
- codeforces 149D Coloring Brackets (区间DP + dfs)
题目链接: codeforces 149D 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 ...
- codeforce 149D Coloring Brackets 区间DP
题目链接:http://codeforces.com/problemset/problem/149/D 继续区间DP啊.... 思路: 定义dp[l][r][c1][c2]表示对于区间(l,r)来说, ...
随机推荐
- Flume定时启动任务 防止挂掉
一,查看Flume条数:ps -ef|grep java|grep flume|wc -l ==>15 检查进程:给sh脚本添加权限,chmod 777 xx.sh #!/bin/s ...
- 【转】如何内网搭建NuGet服务器
原文:http://www.cnblogs.com/zhangweizhong/p/7755332.html NuGet 是.NET程序员熟知的工具,它可以直接安装开源社区中的各个公用组件,可以说是非 ...
- SQL Server 2008 R2 Express Profiler
I successfully installed SQL Server Profiler 2008 R2 Profiler without uninstalling SQL 2008 R2 Expre ...
- d3 js emberjs handlerbarjs
http://handlebarsjs.com/ http://emberjs.com/ http://jsbin.com/d3ember-barchart/13/edit?html,output
- SQL Server Management Studio 评估期已过
SQL2008破解: (1)将SQL安装光盘(或者ISO)放进去运行,进入安装界面. (2)选择“维护”中的“版本升级”,如图: (3)按照版本升级的向导,先输入产品密钥,也就是正式企业版的序列号: ...
- UWP 自然灾害App在刷新数据后卡死的解决方案
一直以为都在纳闷,为啥我的其他app崩溃次数几乎为0,而单单这个App的崩溃次数简直逆天了,我都不敢相信. 每天都有至少上千次crash...我也是服的 不甘心,趁着这次重构的机会,把代码好好捋了1下 ...
- 应用.NET控制台应用程序开发批量导入程序。
一.最近一直在调整去年以及维护去年开发的项目,好久没有在进行个人的博客了.每天抽了一定的时间在研究一些开源的框架,Drapper 以及NHibernate以及当前比较流行的SqlSuper框架 并进行 ...
- 工作之路---记录LZ如何在两年半的时间内升为PM
引言 之前的伪PM纠结之路已经渐渐结束,LZ也终于正式爬上了PM的位置,对于LZ来说,这个时间比LZ预计的早来了两年半.说起来,两年半的速度已经算是比较快了,但这之中的努力唯有LZ一人知晓.写这篇文章 ...
- Win7搭建FTP服务器
“控制面板” -> “程序和功能” -> “打开或关闭Windows 功能”: 1.展开“Internet 信息服务” 2.勾选“Internet Information Services ...
- arduino八段数码管使用
一:八段数码管的使用 控制要求:0-9的计时数据 实物连接图: 控制代码: //智慧自动化2018.6.11 ;//定义数字接口7 连接a 段数码管 ;// 定义数字接口6 连接b 段数码管 ;// ...