CodeForces 149D Coloring Brackets

来源:互联网 发布:高校综合数据分析平台 编辑:程序博客网 时间:2024/04/30 09:41

题目描述:

直接扔连接了-.-
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 1000000007typedef 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;}
0 0