标签:
直接扔连接了-.-
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;
}
CodeForces 149D Coloring Brackets
标签:
原文地址:http://blog.csdn.net/wuxuanyi27/article/details/51347467