CodeForces 149D Coloring Brackets

题目描述:

直接扔连接了-.-
http://codeforces.com/problemset/problem/149/D

题目分析:

括号的填色。
有两种颜色和不填色。
满足:
1.每对括号都要填色。
2.每对括号只有一个(左括号或右括号)能填色,另一个不填色。
3.连续的两个括号不能相同颜色。(当然可以都不填色)

区间DP题。
dp[l][r][c1][c2]表示在区间(l,r)中,l填c1色,r填c2色的情况数。
其中颜色0表示不填色,1和2表示两种被填的颜色。
先在匹配括号,用match[i]表示i的另一半在哪。
搜索,
对l和r的配对情况进行分析,进行处理。具体看代码。

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

const int MAXN = 710;
#define MOD 1000000007
typedef long long ll;
using namespace std;

char s[MAXN];
ll dp[MAXN][MAXN][3][3];
int match[MAXN];

void getmatch(int len)//将'('与')'配对
{
    int tmp[MAXN];
    //这里也可以用stack实现
    int p=0;
    for(int i=0; i<len; i++)
    {
        if (s[i]=='(')
            tmp[p++]=i;
        else
        {
            match[i]=tmp[--p];
            match[tmp[p]]=i;
        }
    }
}

void DP(int l,int r)
{
    if (l+1==r)//搜索边界
    {
        dp[l][r][0][1]=1;
        dp[l][r][0][2]=1;
        dp[l][r][1][0]=1;
        dp[l][r][2][0]=1;
        return;
    }
    if (match[l]==r)//l与r能配对
    {
        DP(l+1,r-1);
        for(int i=0; i<3; i++)
        {
            for(int j=0; j<3; 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;
            }
        }
        return;
    }
    else//l与r不能配对
    {
        int mid=match[l];//找到与l对应的
        DP(l,mid);
        DP(mid+1,r);
        for(int i=0; i<3; i++)
            for(int j=0; j<3; j++)
               for(int c1=0; c1<3; c1++)
                  for(int c2=0; c2<3; c2++)
                  if(!((c1==1 && c2==1) || (c1==2 && c2==2)))
                        dp[l][r][i][j]=(dp[l][r][i][j]+(dp[l][mid][i][c1]*dp[mid+1][r][c2][j])%MOD)%MOD;
                        //也满足连续不会相同颜色
    }
}

int main()
{
    while(~scanf("%s",s))
    {
        int len=strlen(s);
        getmatch(len);
        memset(dp,0,sizeof(dp));
        DP(0,len-1);
        ll ans=0;
        for(int i=0; i<3; i++)
        {
            for(int j=0; j<3; j++)
            {
                if (!(i==0 && j==0))
                ans=(ans+dp[0][len-1][i][j])%MOD;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(dp)