zoukankan      html  css  js  c++  java
  • codeforce 149D Coloring Brackets ----区间dp

    题目大意:给出一组括号,询问你给括号上色的情况数,颜色有两种,要求有两点:

                    ①一对匹配的括号,最多且必须有一个上色,即每一对对应的括号都是一个有颜色,另一个没有颜色。

                    ②相邻的两个字符,不能为同一种颜色,但是可以是都不染色。

    dp[i][j][k1][k2]表示区间[i,j]且i为颜色k1、j为颜色k2时,合法解的数目。我们可以假设0为不染色、1和2为另外两种颜色。

    DP方程有两个部分,第一部分为当i和j为一对匹配的括号时,需要注意满足条件一。

              第二部分为当i匹配的后半括号时,注意条件二来进行状态转移。

    这里分别拿出一个例子来详细说明:

      b[i]为处理出来的辅助数组,值的意义为a[i]字符对应另一半括号的位置。左右括号相互标明。

      ①dp[i][j][0][1]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][1][2]+dp[i+1][j-1][2][0]+dp[i+1][j-1][2][2])%mod; 

         因为左边没染色,右边为颜色1,所以左边i+1无颜色限制而右边的j-1不能为颜色1,能够转移到这个状态的状态有6个。枚举k1,k2的值,并且注意写全能够继承的状态。

      ②  if(k3==0||k4==0||k3!=k4)

        {
          dp[i][j][k1][k2]+=(dp[i][b[i]][k1][k3]*dp[b[i]+1][j][k4][k2])%mod;
          dp[i][j][k1][k2]%=mod;
        }

       枚举k1,k2,k3,k4.此时的 i和 j 一定不匹配,所以可以存在所有的3X3=9种的组合,需要注意的只有相互匹配的k1与k3(受限于条件1)与k3和k4(受限于条件2)。 此情况只有讨论到合法解时值才不为0,如若遇到dp[i][j][0][0]这种,那么会由于值为0而使结果不改变,不影响答案。

           具体代码如下:

    #include<iostream>
    using namespace std;
    #define ll long long
    const ll mod=1000000007;
    ll dp[705][705][3][3];
    int b[705],c[360];
    
    int main()
    {
        string a;
        cin>>a;
        int n=a.size();
        int i,k,j,s=1;
        for(i=0;i<n;i++)
        {
            if(a[i]=='(') c[s++]=i;
            else
            {
                b[c[s-1]]=i;
                b[i]=c[s-1];
                s--;
            }
        }
        for(i=0;i<n-1;i++) 
        if(b[i]==i+1)
        {
            dp[i][i+1][0][1]=dp[i][i+1][1][0]=1;
            dp[i][i+1][0][2]=dp[i][i+1][2][0]=1;
            //dp[i][i+1][0][0]=1;
        }
        for(k=1;k<n;k++)
        for(i=0;i+k<n;i++)
        {
            j=i+k;
            if(b[i]==j)
            {
                dp[i][j][0][1]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][1][2]+dp[i+1][j-1][2][0]+dp[i+1][j-1][2][2])%mod;
                dp[i][j][0][2]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][1]+dp[i+1][j-1][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][2][0]+dp[i+1][j-1][2][1])%mod;
                dp[i][j][1][0]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][2][0]+dp[i+1][j-1][2][1]+dp[i+1][j-1][2][2])%mod;
                dp[i][j][2][0]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][1][2])%mod;
            }
            else if(b[i]<j)
            {
                int k1,k2,k3,k4;
                for(k1=0;k1<=2;k1++)
                for(k2=0;k2<=2;k2++)
                for(k3=0;k3<=2;k3++)
                for(k4=0;k4<=2;k4++)
                {
                    if(k3==0||k4==0||k3!=k4)
                    {
                        dp[i][j][k1][k2]+=(dp[i][b[i]][k1][k3]*dp[b[i]+1][j][k4][k2])%mod;
                        dp[i][j][k1][k2]%=mod;
                    }
                }
            }
        }
        ll ans=0;
        for(i=0;i<=2;i++)
        for(j=0;j<=2;j++)
        {
            //cout<<dp[0][n-1][i][j]<<endl;
            ans=(ans+dp[0][n-1][i][j])%mod;
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    js转化 保留2位小数
    python练习:打印九九乘法表
    PyCharm常用快捷键及工具
    python关键字
    Python学习资源
    Jira项目导入,被导入项目与目的系统数据类型不一致导入不成功的解决方案
    压测的时候到底要不要加集合点?
    Java Vuser协议JDBC脚本编写(MySQL)
    eclipse工具使用
    oracle忘记sys,system密码的解决方法
  • 原文地址:https://www.cnblogs.com/wsblm/p/10713039.html
Copyright © 2011-2022 走看看