zoukankan      html  css  js  c++  java
  • CF149D Coloring Brackets

    题目

    洛谷
    CF

    题解

    考虑DP

    先由范围盲猜一波 分析复杂度可得: (O(n^2))
    所以先设 dp[l][r] 表示处理l~r区间的答案
    但对于区间l~r的状态而言,显然是不够的,还要再记录l和r的颜色
    所以dp[l][r][x][y]表示l颜色为x, r颜色为y ((0<=x,y<=2))

    考虑如何转移

    具体通过记忆化搜索实现
    我们需要在转移的过程中保证l位置始终是"(",r位置")"
    对于l,r的不同关系,我们会有3种不同的转移:

    1.l+1=r: 返回x,y是否合法

    2.r和l是一对匹配的括号: (枚举l+1,r-1的颜色i,j转移) dp[l][r][x][y]+=dp[l+1][r-1][i][j]

    3.没有关系: (与r匹配的左括号left[r]一定会出现在l~r之间)

    枚举left[r]的颜色j和left[r]-1的颜色i,然后把两块区间的答案乘起来

    即:dp[l][r][x][y]+=dp[l][left[r]-1][x][i]*dp[left[r]][r][j][y]

    然后就是一堆判颜色合法的细节

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define re register
    #define in inline
    #define ll long long
    #define get getchar()
    #define right ri
    #define left le
    #define int ll
    const int _=755;
    const int mod=1e9+7;
    int st[_];
    int n,top,left[_],right[_];
    char s[_];
    ll dp[_][_][3][3];
    in bool check(int l,int r,int x,int y)
    {
        if(right[l]!=r) return 1;
        if(x>0&&y>0) return 0;
        if(x==0 && y==0) return 0;
        return 1;
    } //判断l,r是否合法(若l,r无关系则必定合法)
    in int dfs(int l,int r,int x,int y)
    {
        if(dp[l][r][x][y]) return dp[l][r][x][y];
        if(!check(l,r,x,y)) return 0;
        if(l+1==r){
            dp[l][r][x][y]=1;
            return 1;
        }
        for(re int i=0;i<=2;i++)
            for(re int j=0;j<=2;j++) {
                if(left[r]==l) {
                    if((j>0 && j==y) || (i>0 && x==i)) continue;
                    dp[l][r][x][y]=(dp[l][r][x][y]+dfs(l+1,r-1,i,j))%mod;
                }
                else {
                    if((!check(left[r],r,j,y)) || (!check(l,left[r]-1,x,i))) continue;
                    if(j==i && i>0) continue;
                    dp[l][r][x][y]=(dp[l][r][x][y]+dfs(left[r],r,j,y)*dfs(l,left[r]-1,x,i)%mod)%mod;
                }
            }
        return dp[l][r][x][y];
    }
    signed main()
    {
        scanf("%s",s+1);
        n=strlen(s+1);
        st[top]=1;
        for(re int i=2;i<=n;i++) {
            if(s[i]==')')
                right[st[top]]=i,left[i]=st[top--];
            else st[++top]=i;
        } //预处理每个括号对应的括号的位置
        ll ans=0;
        for(re int i=0;i<=2;i++)
            for(re int j=0;j<=2;j++) {
                ans=(ans+dfs(1,n,i,j))%mod;
            }
        cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    centos 7.0.1406 临时环境jenkins安装
    jenkins 登录提示无效
    ubuntu 16.04 安装完QQ后,更新或apt-get报错
    Web服务网站故障分析常用的命令
    在CentOS7中给docker加权限
    aliyun阿里云Maven仓库地址和其他地址
    python 安装 docker-copmose
    mysql 1055错误
    linux 添加用户
    firewall 开启服务
  • 原文地址:https://www.cnblogs.com/yzhx/p/13908096.html
Copyright © 2011-2022 走看看