• 「Codeforces」149D(dfs+区间dp)


    题意:原题在这

    给出一个配对的括号序列(如"(())()"、"()"等, ")()"、"(()"是不符合要求的 ),对该序列按以下方法进行染色: 1.一个括号可以染红色、蓝色或不染色 2.一对匹配的括号需要且只能将其中一个染色 3.相邻两个括号颜色不能相同(但可以都不染色) 求符合条件的染色方案数(对1000000007取模) 输入:

    一行,表示括号序列 输出:

    一个数表示方案数(对1000000007取模) 数据范围:

    2<=序列长度<=700

    做法:详见行内注释)

    1. 情况:

      (1)首尾直接连接
      (2)某个括号的结尾刚好为串尾
      (3)相邻不同色

    2. dp[l][r][0/1/2][0/1/2]表示括号区间[l,r]左/右染色情况下的最大方法数

    3. 预处理,dfs,输出dp范围一定是[0,n);

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define maxn 99999999
    #define mod 1000000007
    using namespace std;
    string s;
    int n,cnt=-1;
    int head[950],tail[950];
    long long ans=0;
    long long dp[950][950][5][5];
    
    
    void dfs(int l,int r)
    {
        //if(l>r) return 1;
        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;
            return;
        }
    
        else if(tail[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+1][r-1][i][j]+dp[l][r][0][1])%mod;
                if(j!=2) dp[l][r][0][2]=(dp[l+1][r-1][i][j]+dp[l][r][0][2])%mod;
                if(i!=1) dp[l][r][1][0]=(dp[l+1][r-1][i][j]+dp[l][r][1][0])%mod;
                if(i!=2) dp[l][r][2][0]=(dp[l+1][r-1][i][j]+dp[l][r][2][0])%mod;
            }
            return;
        }
    
        else
        {//第二种情况
            dfs(l,tail[l]);
            dfs(tail[l]+1,r);
            for(int i=0;i<=2;i++)
            for(int j=0;j<=2;j++)
            for(int f=0;f<=2;f++)
            for(int k=0;k<=2;k++)
            {//颜色不能一样
                if(j==1&&f==1) continue;
                if(j==2&&f==2) continue;
                dp[l][r][i][k]=(dp[l][r][i][k]+(dp[l][tail[l]][i][j]*dp[tail[l]+1][r][f][k])%mod)%mod;
            }
            return;
        }
    }
    
    int main()
    {
        cin>>s;
        n=s.size();
        for(int i=0;i<n;i++)//预处理每一个括号的另一半
        {
            if (s[i]=='(') head[cnt++]=i;
            else tail[head[--cnt]]=i;
        }
        dfs(0,n-1);
        for(int i=0;i<=2;i++)
        for(int j=0;j<=2;j++)
        {
            ans+=dp[0][n-1][i][j];   
        }
        ans%=mod;
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    U10783 名字被和谐了
    P1151 子数整数
    P2756 飞行员配对方案问题
    P3227 [HNOI2013]切糕
    BZOJ 2127: happiness(最小割解决集合划分)
    linux脚本初体验
    130902 周赛
    Citrix 服务器虚拟化之三十二 XenConvert
    数据字典统一管理,动态下拉框
    [置顶] oracle 数据库表中转换成java代码
  • 原文地址:https://www.cnblogs.com/LocaEtric/p/9615707.html
Copyright © 2020-2023  润新知