题目大意
给一个给定括号序列,给该括号上色,上色有三个要求
1、只有三种上色方案,不上色,上红色,上蓝色
2、每对括号必须只能给其中的一个上色
3、相邻的两个不能上同色,可以都不上色
求0-len-1这一区间内有多少种上色方案,很明显的区间DP
dp[l][r][i][j]表示l-r区间两端颜色分别是i,j的方案数
0代表不上色,1代表上红色,2代表上蓝色
对于l-r区间,有3种情况
1、if(l+1==r) 说明就只有一对,那么dp[l][r][0][1]=1;
dp[l][r][1][0]=1;
dp[l][r][0][2]=1;
dp[l][r][2][0]=1;
2、if(l与r是配对的)
递归(l+1,r-1)
状态转移dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod; dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod;
dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod; dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod;
3、if(l与r不配对)
dp[l][r][i][j]=(dp[l][r][i][j]+(dp[l][p][i][k]*dp[p+1][r][q][j])%mod)%mod;
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#pragma warning(disable:4996)
using namespace std;
typedef long long ll;
const int maxn = 1005;
char s[maxn];
int match[maxn];
int tmp[maxn];
const int mod = 1e9 + 7;
ll dp[maxn][maxn][5][5];
void get_match(int len) {
int cnt = 0;
for (int i = 0; i < len; i++) {
if (s[i] == '(') {
tmp[cnt++] = i;
}
else
{
match[i] = tmp[cnt - 1];
match[tmp[cnt - 1]] = i;
cnt--;
}
}
}
void dfs(int l, int r) {
if (l + 1 == r) {
dp[l][r][1][0] = 1;
dp[l][r][2][0] = 1;
dp[l][r][0][1] = 1;
dp[l][r][0][2] = 1;
return;
}
if (match[l] == r) {
dfs(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
{
int p = match[l];
dfs(l, p);
dfs(p + 1, r);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
for (int q = 0; q < 3; q++) {
if (!((k == 1 && q == 1) || (k == 2 && q == 2))) {
dp[l][r][i][j] = (dp[l][r][i][j] + (dp[l][p][i][k] * dp[p + 1][r][q][j]) % mod) % mod;
}
}
}
}
}
}
}
int main() {
while (scanf("%s", s) != EOF) {
int len = strlen(s);
get_match(len);
memset(dp, 0, sizeof(dp));
dfs(0, len - 1);
ll ans = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
ans = (ans + dp[0][len - 1][i][j]) % mod;
}
}
printf("%lld\n", ans);
}
return 0;
}
476

被折叠的 条评论
为什么被折叠?



