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)来说, ...
随机推荐
- hive介绍、安装配置、表操作基础知识适合小白学习
1.hive概述 Apache Hive数据仓库软件有助于使用SQL读取,编写和管理驻留在分布式存储中的大型数据集.可以将结构投影到已存储的数据中.提供了命令行工具和JDBC驱动以将用户连接到Hive ...
- 函数的返回值是void
#include <stdio.h> void sub(int x,int y,int z){ z=y-x; } void main() { int a=1,b=2,c=3; sub(10 ...
- RabbitMQ(一):Window安装RabbitMQ
原文:RabbitMQ(一):Window安装RabbitMQ 1.安装ERLANG语言环境 由于RabbitMQ是采用Erlang编写的,因此我们需要先安装该语言库,以便运行代理服务器.从Erlan ...
- Noip前的大抱佛脚----文章索引
Noip前的大抱佛脚----赛前任务 Noip前的大抱佛脚----考场配置 Noip前的大抱佛脚----数论 Noip前的大抱佛脚----图论 Noip前的大抱佛脚----动态规划 Noip前的大抱佛 ...
- NLPIR分词(c++接口整理)
C/C++接口——对应的各个函数 函数1-bool NLPIR_Init(const char * sInitDirPath=0, int encoding=GBK_CODE,constchar*sL ...
- 2018年美国大学生数学建模竞赛(MCM/ICM) E题解题思路
任务一就是让大家去做个基本的评价,是典型的评价类问题,所以应该按照 指标+方法的步骤去做,首先就是寻找国家脆弱性的相关概念,然后选择影响国 家脆弱性的指标,如气候变化,经济发展,政治状况等等,再就是构 ...
- flask入门补充
在上篇文章提到了json的编码问题.那么Flask是国外开发的框架,没有考虑到中文编码,那么我们就需要自己配置 那么在访问页面的时候会有 get 请求和post 请求.在下边我也会提到.以及没有接触 ...
- Andorid Studio 模块化开发相关配置
Andorid Studio 模块化开发相关配置 下面以宿主APP模块和Uer_Module模块为例: 第一步:在项目根目录gradle.properties配置文件中添加如下代码 isNeedUse ...
- Tensorflow张量的形状表示方法
对输入或输出而言: 一个张量的形状为a x b x c x d,实际写出这个张量时: 最外层括号[…]表示这个是一个张量,无别的意义! 次外层括号有a个,表示这个张量里有a个样本 再往内的括号有b个, ...
- dstat 性能测试工具常用选项
dstat常用的选项有: -c 显示cpu使用情况 -d 显示磁盘使用情况 -g, 显示页面数据 -i 启用中断数据 -l 平均负载统计(1分钟,5分钟,1 ...