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;
    }
  • 相关阅读:
    Matlab 绘制三维立体图(以地质异常体为例)
    Azure DevOps的variable group实现array和hashtable参数的传递
    Azure DevOps 利用rest api设置variable group
    Azure AADSTS7000215 其中一种问题的解决
    Power BI 实现实时更新Streaming Dataset
    AAD Service Principal获取azure user list (Microsoft Graph API)
    Matlab 沿三维任意方向切割CT图的仿真计算
    Azure Powershell script检测登陆并部署ARM Template
    Azure KeyVault设置策略和自动化添加secrets键值对
    Azure登陆的两种常见方式(user 和 service principal登陆)
  • 原文地址:https://www.cnblogs.com/wsblm/p/10713039.html
Copyright © 2011-2022 走看看