CodeForces 149D Coloring Brackets (区间D)

题意:

  给一个合法的括号序列,仅含()这两种。现在要为每对括号中的其中一个括号上色,有两种可选:蓝or红。要求不能有两个同颜色的括号相邻,问有多少种染色的方法?

思路:

  这题的模拟成分比较多吧?两种颜色还有无色,用2个bit就可以表示了。然后就是各种转移,注意结果可能非常大,要取模后输出。转移主要是不让同颜色的括号在一起。处理时可以用DFS,在区间[L,R]中找到距离最远的所有合法括号,递归往下处理子问题,直到剩下一对括号直接处理就行了。

 1 //#include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <map>
 7 #include <algorithm>
 8 #include <vector>
 9 #include <iostream>
10 #define pii pair<int,int>
11 #define INF 0x3f3f3f3f
12 #define LL unsigned long long
13 using namespace std;
14 const double PI  = acos(-1.0);
15 const int N=1000;
16 const int mod=1e9+7;
17 char s[N];
18
19 LL dp[N][N][3][3];  //0无色,1红色,2蓝色
20
21 void cal(int ll,int mid,int rr) //区间合并
22 {
23     if(ll==mid) return ;
24     for(int i=0; i<3; i++)
25     for(int j=0; j<3; j++)
26     for(int k=0; k<3; k++)
27     for(int u=0; u<3; u++)
28     if(k!=u||k==0)
29     dp[ll][rr][i][j]+=(dp[ll][mid-1][i][k] * dp[mid][rr][u][j])%mod;
30 }
31 void cal2(int ll,int rr)    //区间嵌套的
32 {
33     for(int k=0; k<3; k++)      //枚举内区间
34     for(int u=0; u<3; u++)
35     {
36         if( u!=1 )    dp[ll][rr][0][1]=(dp[ll][rr][0][1]+dp[ll+1][rr-1][k][u])%mod;
37         if( u!=2 )    dp[ll][rr][0][2]=(dp[ll][rr][0][2]+dp[ll+1][rr-1][k][u])%mod;
38         if( k!=1 )    dp[ll][rr][1][0]=(dp[ll][rr][1][0]+dp[ll+1][rr-1][k][u])%mod;
39         if( k!=2 )    dp[ll][rr][2][0]=(dp[ll][rr][2][0]+dp[ll+1][rr-1][k][u])%mod;
40     }
41 }
42
43 void DFS(int L,int R)
44 {
45     if(L+1==R)
46     {
47         dp[L][R][1][0]=dp[L][R][0][1]=1;
48         dp[L][R][2][0]=dp[L][R][0][2]=1;
49         return ;
50     }
51     int q=L+1;
52     while( q<R )   //将[L->R]分成多个子区间
53     {
54         int p=q, cnt=0;
55         while( 1 )  //找对应的另一半括号)的位置
56         {
57             if( s[q]==‘(‘ ) cnt++;
58             if( s[q]==‘)‘ ) cnt--;
59             if(cnt==0)      break;
60             q++;
61         }
62         DFS(p, q);      //计算区间[p->q]
63         cal(L+1, p, q); //两个区间合并
64         q++;
65     }
66     cal2(L,R);          //子区间并到大区间
67 }
68
69
70 int main()
71 {
72     //freopen("input.txt", "r", stdin);
73     memset(dp,0,sizeof(dp));
74     scanf("%s",s+1);
75     int n=strlen(s+1);
76     DFS(0, n+1);    //将s[0]和s[n+1]视为一对括号比较好处理
77     LL ans=0;
78
79     for(int i=0; i<3; i++)
80         for(int j=0; j<3; j++)
81             ans=(ans+dp[1][n][i][j])%mod;
82
83     cout<<ans<<endl;
84     return 0;
85 }

AC代码

时间: 2024-12-11 05:56:56

CodeForces 149D Coloring Brackets (区间D)的相关文章

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

codeferces 149D Coloring Brackets 区间dp

http://codeforces.com/problemset/problem/149/D 题目大致意思是给你一串字符串,只有小括号,并且已经符合括号匹配规则,现在要给这些括号涂色,给出一些涂色规则,求涂色的方案数. 1: 括号要么不被涂色,要么被涂成蓝色,要么被涂成红色. 2:两个相互匹配的括号有且仅有一个被涂色. 3:相邻两个括号不可以有相同颜色. 这里当然也是想到对区 [l, r] 间进行dp,但是这里对颜色有依赖关系,所以还需要记入 l 和 r 颜色的状态,一开始打算只用一维记录两个点

CodeForces 149D Coloring Brackets

区间DP.dp[i][j][h][k]表示[i,j]这段区间染色,左端点为颜色h,右端点为颜色k的方案数. 递推式很容易写出来.注意中间过程爆int. #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int MOD = 1e9 + 7; const int max

CF149D. Coloring Brackets[区间DP !]

不知道为什么居中了,先把代码放这 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=705,MOD=1e9+7; char s[N]; long long n,f[N][N][5][5]; int st[N],top=0,m[N]; void match(){ for(int i=1;i<=

CF# 149 D Coloring Brackets(区间dp)

D - Coloring Brackets Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 149D Description Once Petya read a problem about a bracket sequence. He gave it much thought but didn't find a solut

CodeForces 149D 区间DP Coloring Brackets

染色有三个条件: 对于每个点来说要么不染色,要么染红色,要么染蓝色 对于每对配对的括号来说,有且只有一个一边的括号被染色 相邻的括号不能染成相同的颜色 首先可以根据给出的括号序列计算出括号的配对情况,具体来说就是第i个括号与R[i]个括号配对. 对于一个正规配对括号序列(correct bracket sequence),d(l, r, c1, c2)表示括号序列S[i]~S[j],i左边括号的颜色是c1,r右边的括号颜色是c2(0表示没有染色),这样的序列的染色方法数. 与S[i]配对的可能是

Codeforces Round #106 (Div. 2) Coloring Brackets(区间DP)

题意:给你一组括号序列,让你进行染色,对于每个括号,有无色,红色,蓝色三种方案.染色需要满足这样的条件:互相匹配的括号,有且只有一个有颜色,相邻的括号不能颜色相同(可以同为无色),问合法的染色方案数(答案%1e9+7) 分析:根据题意能够看出是区间DP,并且状态转移的时候,依赖于左右两端的颜色,所以我们用dp[i][j][x][y]表示i到j的区间内左端颜色为x,右端颜色为y的方案数. 区间[i,j]可以由两种情况得到,一种是str[i],str[j]匹配,产生新的相匹配的括号,考虑在只有一端染

POJ 2955 Brackets (区间dp 括号匹配)

Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3951   Accepted: 2078 Description We give the following inductive definition of a "regular brackets" sequence: the empty sequence is a regular brackets sequence, if s is a reg

Codeforces 509F Progress Monitoring (区间dp 或 记忆化搜索)

F. Progress Monitoring time limit per test 1 second memory limit per test 256 megabytes Programming teacher Dmitry Olegovich is going to propose the following task for one of his tests for students: You are given a tree T with n vertices, specified b