codeforces 149D Coloring Brackets 区间DP
2017-02-18 16:56
627 查看
题意:给你一串括号,每个括号可以涂色,蓝色或者红色或者不涂,问你有多少种方案数,其中涂色有些限制。
1.每对括号有且仅有其中一个被涂色。
2.相邻的括号不能涂相同的颜色,但是相邻的括号可以同时不涂色。
那我们怎么做呢。
首先他已经给出了一个合法的括号序列,我们只要找每个左括号右边的第一个右括号就可以了,设dp[l][r][x][y]表示l到r这段区间的答案,l和r的颜色分别为x和y的方案数(0/1/2)。
那么dp有三种转移。
第一种l+1=r时。其实和初始化差不多。
dp[l][r][2][0]=1;
dp[l][r][0][2]=1;
dp[l][r][1][0]=1;
dp[l][r][0][1]=1;
相邻的括号不能都涂色。
第二种,r和l是一对匹配的括号。
这种情况下我们要计算l和r区间内合法的方案,简单来说就是括号套括号。转移如下:
dfs(l+1,r-1);
fo(i,0,2)
fo(j,0,2)
{
if (j!=1)
dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mo;
if (i!=1)
dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mo;
if (j!=2)
dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mo;
if (i!=2)
dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mo;
}
这个自己推一推都能知道。
第三种:普通情况,l和r没什么关系,这种情况其实就是矩阵连乘。。。
设mid表示和l匹配的那个括号。
dp[l][r][i][j]+=dp[l][mid][i][x]*dp[mid+1][r][y][j];
然后整个dp过程是用搜索完成的。。
1.每对括号有且仅有其中一个被涂色。
2.相邻的括号不能涂相同的颜色,但是相邻的括号可以同时不涂色。
那我们怎么做呢。
首先他已经给出了一个合法的括号序列,我们只要找每个左括号右边的第一个右括号就可以了,设dp[l][r][x][y]表示l到r这段区间的答案,l和r的颜色分别为x和y的方案数(0/1/2)。
那么dp有三种转移。
第一种l+1=r时。其实和初始化差不多。
dp[l][r][2][0]=1;
dp[l][r][0][2]=1;
dp[l][r][1][0]=1;
dp[l][r][0][1]=1;
相邻的括号不能都涂色。
第二种,r和l是一对匹配的括号。
这种情况下我们要计算l和r区间内合法的方案,简单来说就是括号套括号。转移如下:
dfs(l+1,r-1);
fo(i,0,2)
fo(j,0,2)
{
if (j!=1)
dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mo;
if (i!=1)
dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mo;
if (j!=2)
dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mo;
if (i!=2)
dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mo;
}
这个自己推一推都能知道。
第三种:普通情况,l和r没什么关系,这种情况其实就是矩阵连乘。。。
设mid表示和l匹配的那个括号。
dp[l][r][i][j]+=dp[l][mid][i][x]*dp[mid+1][r][y][j];
然后整个dp过程是用搜索完成的。。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; typedef long long ll; const int N=1e3; const int mo=1e9+7; const int inf=1e9; int dp [3][3],a ,match ,b ; char s ; int tot,len; inline void get() { int tot=0; fo(i,0,len-1) { if (s[i]=='(')b[tot++]=i; else { match[i]=b[tot-1]; match[b[tot-1]]=i; tot--; } } } inline void dfs(int l,int r) { if (l+1==r) { dp[l][r][2][0]=1; dp[l][r][0][2]=1; dp[l][r][1][0]=1; dp[l][r][0][1]=1; return; } else if (match[l]==r) { dfs(l+1,r-1); fo(i,0,2) fo(j,0,2) { if (j!=1) dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mo; if (i!=1) dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mo; if (j!=2) dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mo; if (i!=2) dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mo; } return; } else { int nu=match[l]; dfs(l,nu); dfs(nu+1,r); fo(i,0,2) { fo(j,0,2) { fo(x,0,2) { fo(y,0,2) { if (!(x==1&&y==1 || x==2&&y==2)) dp[l][r][i][j]=(dp[l][r][i][j]+dp[l][nu][i][x]*dp[nu+1][r][y][j])%mo; } } } } } } int main() { while(scanf("%s",s)!=EOF) { len=strlen(s); memset(dp,0,sizeof(dp)); get(); dfs(0,len-1); ll ans=0; fo(i,0,2) fo(j,0,2) ans=(ans+dp[0][len-1][i][j])%mo; 4000 printf("%lld\n",ans); } }
相关文章推荐
- codeforces 149D Coloring Brackets(区间dp)
- Codeforces 149D Coloring Brackets(区间dp)
- codeforces 149D - Coloring Brackets (区间dp)
- CodeForces - 149D Coloring Brackets 详细题解(递归区间DP+dfs染色,好题)
- Codeforces-149D-Coloring Brackets【区间DP】
- CodeForces 149D-Coloring Brackets(区间dp 的好题)
- CodeForces - 149D Coloring Brackets(区间dp)
- Codeforces 149D - Coloring Brackets(区间DP)
- CodeForces 149D 区间DP Coloring Brackets
- CodeForces 149D Coloring Brackets 区间DP
- CodeForces 149D Coloring Brackets(区间DP)
- CodeForces 149D Coloring Brackets(区间DP+dfs)
- CodeForces 149D Coloring Brackets(区间DP)
- codeforces 149D Coloring Brackets (区间DP + dfs)
- Codeforces 149D Coloring Brackets 【区间dp】
- CodeForces - 149D Coloring Brackets(区间DP)
- CodeForces - 149D Coloring Brackets[区间dp]
- Codeforces 149D Coloring Brackets (不错的区间DP)
- CodeForces - 149DColoring Brackets(区间DP)
- CodeForces 149D Coloring Brackets(区间dp)