栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

CF149D Coloring Brackets 题解

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

CF149D Coloring Brackets 题解

CF149D Coloring Brackets 题解

题目链接:CF149D Coloring Brackets

题意:给出一个配对的括号序列(如 “ (())() texttt{(())()} (())()”、“ () texttt{()} ()” 等,“ )() texttt{)()} )()”、“ (() texttt{(()} (()”是不符合要求的),对该序列按照以下方法染色。

  1. 一个括号可以染成红色、蓝色或者不染色。
  2. 一对匹配的括号需要且只能将其中一个染色。
  3. 相邻两个括号颜色不能相同(但都可以不染色)。

求符合条件的染色方案数,对 1000000007 1000000007 1000000007 取模。

容易发现这个题目就是个区间dp

但是仅仅用 d p [ l ] [ r ] dp[l][r] dp[l][r] 并不能表示出两侧括号的颜色

因此设 d p [ l ] [ r ] [ i ] [ j ] dp[l][r][i][j] dp[l][r][i][j] 为区间 [ l , r ] [l,r] [l,r] 内且左右两侧的颜色分别为 i , j i,j i,j 时的方案数 (0为不染色,1为红,2为蓝)

考虑边界:当 l + 1 = r l+1=r l+1=r 时,有
() text{()} ()

dp[l][r][0][1]=dp[l][r][0][2]=dp[l][r][1][0]=dp[l][r][2][0]=1;

一般地,

当 l l l 与 r r r 配对时,有
( … ) text{(}dotstext{)} (…)

for(int i=0; i<=2; i++)
    for(int j=0; j<=2; j++)
    {
        if(j!=1) dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod;
        if(j!=2) dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod;
        if(i!=1) dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod;
        if(i!=2) dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod;
    }

当 l l l 与 r r r 不配对时,有
( … ) … ( … ) text{(}dotstext{)}dotstext{(}dotstext{)} (…)…(…)
以及
( … )( … ) text{(}dotstext{)}text{(}dotstext{)} (…)(…)
等情况,不过本质上是一样的

for(int i=0; i<=2; i++)
    for(int j=0; j<=2; j++)
        for(int p=0; p<=2; p++)
            for(int q=0; q<=2; q++)
            {
                if(j==1&&p==1||j==2&&p==2)continue;
                dp[l][r][i][q]=(dp[l][r][i][q]+dp[l][mch[l]][i][j]*dp[mch[l]+1][r][p][q]%mod)%mod;
            }

值得注意的是,本题并不适用一般的dp顺序,而是采用记忆化搜索

因为本题要求配对的括号有且仅有一个被染色,而一般的顺序难以保证配对的括号在同一个区间内,即不能保证转移中用到的序列都是合法的,因此较为麻烦

代码:

#include 
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(705)
const int mod=1e9+7;
char a[N];
int n,mch[N],stk[N],top,dp[N][N][3][3];
void dfs(int l,int r)
{
    if(l+1==r)dp[l][r][0][1]=dp[l][r][0][2]=dp[l][r][1][0]=dp[l][r][2][0]=1;
    else if(mch[l]==r)
    {
        dfs(l+1,r-1);
        for(int i=0; i<=2; i++)
            for(int j=0; j<=2; j++)
            {
                if(j!=1) dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod;
		        if(j!=2) dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod;
		        if(i!=1) dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod;
		        if(i!=2) dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod;
            }
    }else
    {
        dfs(l,mch[l]);dfs(mch[l]+1,r);
        for(int i=0; i<=2; i++)
            for(int j=0; j<=2; j++)
                for(int p=0; p<=2; p++)
                    for(int q=0; q<=2; q++)
                    {
                        if(j==1&&p==1||j==2&&p==2)continue;
                        dp[l][r][i][q]=(dp[l][r][i][q]+dp[l][mch[l]][i][j]*dp[mch[l]+1][r][p][q]%mod)%mod;
                    }
                        
    }
}
signed main()
{
    scanf("%s",(a+1));
    n=strlen(a+1);
    for(int i=1; i<=n; i++)
    {
        if(a[i]=='(')stk[++top]=i;
        else mch[stk[top]]=i,mch[i]=stk[top],--top;
    }
    dfs(1,n);
    int ans=0;
    for(int i=0; i<=2; i++)
        for(int j=0; j<=2; j++)
            ans=(ans+dp[1][n][i][j])%mod;
    printf("%lldn",ans);
    return 0;
}

本文很多地方参考了这篇文章,写的非常好 ✅ ✅ ✅

转载请说明出处

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/893088.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号