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)来说, ...
随机推荐
- PHP分行打印数组-php输出数组方法大全
我们都知道php有两种方式可以打印数组 $arr = array( "a"=>"orange", "b"=>"bana ...
- 提高PHP开发效率, PhpStorm必装的几款插件
1. Translation 最好用的翻译插件 对于我等英文不好的同学来说,简直是福音. 打开翻译对话框 : Ctrl + Shift + O(英文字母o) 鼠标取词并翻译 : Ctrl + Shif ...
- webdriver 获取页面response
在selenium webdriver实现自动化抓取数据过程中,发现无法从webdriver获取页面response 查来查去最终在 stackoverflow 上找到了这一篇文章 文章中说:webd ...
- C语言编译过程以及gcc编译参数
1.1 C语言编译过程,gcc参数简介 1.1.1 C语言编译过程 一.gcc - o a a.c -o:指定文件输出名字 二.C语言编译的过程: 1.1.1 ...
- Codeforces 862D. Mahmoud and Ehab and the binary string (二分)
题目链接:Mahmoud and Ehab and the binary string 题意: 一道交互题,首先给出一个字符串的长度l.现在让你进行提问(最多15次),每次提问提出一个字符串,会返回这 ...
- Linux常用系统命令大全
最近都在和Linux打交道,感觉还不错.我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因,比较短小但却功能强大.我将我了解到的命令列举一 ...
- IDEA中java文件的左下角有个像乐符一样的J符号
- $(document).ready(function() 与window.onload
$(document).ready(function() window.onload 事件是页面完全加载完的时候执行$(function(){ }) 是等页面上的标签加载完了就执行 页面加载完成后开始 ...
- js简单时间比较的方法(转)
//时间比较(yyyy-MM-dd) function compareDate(startDate, endDate) { var arrStart = startDate.split(" ...
- python002
1.万恶的”+“号字符串拼接 字符串中的连接符+”会开辟一个新的空间,多一个“+“就会多开辟一个空间,影响性能 2.字符串格式化 ”%S“ :字符类型 ”%D“ ”数字类型 ...