码迷,mamicode.com
首页 > 其他好文 > 详细

CF149D Coloring Brackets

时间:2020-05-08 09:30:46      阅读:48      评论:0      收藏:0      [点我收藏+]

标签:%s   gis   pre   完整   (())   class   const   区间   while   

给一个合法的括号序列。求满足以下条件的染色方案。
1.一个括号可以染红色、蓝色或不染色 2.一对匹配的括号需要且只能将其中一个染色 3.相邻两个括号颜色不能相同(但可以都不染色) 求符合条件的染色方案数(对1000000007取模)
输入:
一行,表示括号序列 输出:
一个数表示方案数(对1000000007取模)
数据范围:2<=序列长度<=700 翻译贡献者:hhz6830975

输入输出样例
输入1
(())
输出1
12
输入2
(()())
输出2
40
输入3
()
输出3
4

\(dp[l][r][i][j]\) 表示在区间\([l,r]\),\(l\)处颜色是i,\(r\)处是j
0 表示无色, 1 表示红色, 2表示蓝色。
显然的是这个符合一个递归的结构。那么设计一个函数\(solve(l , r)\) 表示求出\(dp[l][r][*][*]\)
分情况讨论,

  1. \(l + 1 == r\) \(dp[l][r][i][0] = dpl][r][0][i] = 1\ (1 <= i <= 2)\)
    (不能有 \(dp[l][r][0][0]\) , 不符合条件2);
  2. 若是这种\((()())\) 或者是\((())\)
    就要先求出\(dp[l+1][r-1]\) , 在和外面的合并,注意里面的\(l+1 , r-1\)不一定是匹配的。
  3. 还有一种是\(()()\)
    这个找到第一个完整的括号序列的位置比如\(()(()) \ \ pos = 2\)
    之后也是合并,同样注意后面的那个不一定是两端匹配的。

最后统计答案,也是整的序列的左右端点不一定匹配(说了三遍了,也错了三次。。。)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<bitset>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int N = 720 , mod = 1e9+7;
inline int read()
{
    register int x = 0 , f = 0; register char c = getchar();
    while(c < ‘0‘ || c > ‘9‘) f |= c == ‘-‘ , c = getchar();
    while(c >= ‘0‘ && c <= ‘9‘) x = (x << 3) + (x << 1) + c - ‘0‘ , c = getchar();
    return f ? -x : x;
}
int n;
char s[N];
int dp[N][N][3][3];
inline int add(int a , int b) { a += b; return a >= mod ? a - mod : a; }
inline int mul(int a , int b) { return (LL)a * b % mod; }
void solve(int l , int r)
{
	if(l + 1 == r) 
	{
		for(int i = 1 ; i <= 2 ; ++i) dp[l][r][i][0] = dp[l][r][0][i] = 1;
		return ;
	}
	int res = 0;
	for(int pos = l ; pos <  r ; ++pos)
	{
		res += s[pos] == ‘(‘ ? 1 : -1;
		if(res == 0)
		{
			solve(l , pos); solve(pos+1 , r); // 右侧的pos+1 与 r不一定是匹配的。 
//			for(int i = 1 ; i <= 2 ; ++i)
//			{
//				dp[l][r][i][0] = mul(dp[l][pos][i][0] , add(dp[pos+1][r][i][0] , dp[pos+1][r][3-i][0]));
//				dp[l][r][0][i] = mul(dp[pos+1][r][0][i] , add(dp[l][pos][0][i] , dp[l][pos][0][3-i]));
//			}
			for(int i = 0 ; i <= 2 ; ++i)
				for(int j = 0 ; j <= 2 ; ++j)
					for(int k = 0 ; k <= 2 ; ++k)
						for(int s = 0 ; s <= 2 ; ++s)
							if(!((k == 1 && s == 1) || (k == 2 && s == 2)))
								dp[l][r][i][j] = add(dp[l][r][i][j] , mul(dp[l][pos][i][k] , dp[pos+1][r][s][j]));
			return ;
		}
	}
	solve(l + 1 , r - 1);
//	for(int i = 1 ; i <= 2 ; ++i) // (()) 这个只能处理这种 
//	{
//		int &res1 = dp[l][r][i][0];
//		for(int j = 0 ; j <= 2 ; ++j) if(j != i) res1 = add(res1 , dp[l+1][r-1][j][0]);
//		for(int j = 0 ; j <= 2 ; ++j) res1 = add(res1 , dp[l+1][r-1][0][j]);
//		int &res2 = dp[l][r][0][i];
//		for(int j = 0 ; j <= 2 ; ++j) if(j != i) res2 = add(res2 , dp[l+1][r-1][0][j]);
//		for(int j = 0 ; j <= 2 ; ++j) res2 = add(res2 , dp[l+1][r-1][j][0]);
//	}
	for(int i = 1 ; i <= 2 ; ++i) // (()()) // 这个都可以 
	{
		int &res1 = dp[l][r][i][0];
		for(int j = 0 ; j <= 2 ; ++j) for(int k = 0 ; k <= 2 ; ++k) if(j != i) res1 = add(res1 , dp[l+1][r-1][j][k]);
		int &res2 = dp[l][r][0][i];
		for(int j = 0 ; j <= 2 ; ++j) for(int k = 0 ; k <= 2 ; ++k) if(k != i) res2 = add(res2 , dp[l+1][r-1][j][k]);
	}
	return ;
}

int main()
{
	scanf("%s" , s+1); n = strlen(s+1);
	solve(1 , n);
	int ans = 0;
//	for(int i = 1 ; i <= 2 ; ++i) ans = add(ans , add(dp[1][n][i][0] , dp[1][n][0][i]));
	for(int i = 0 ; i <= 2 ; ++i) for(int j = 0 ; j <= 2 ; ++j) ans = add(ans , dp[1][n][i][j]);
	cout << ans << ‘\n‘;
	return 0;
}

CF149D Coloring Brackets

标签:%s   gis   pre   完整   (())   class   const   区间   while   

原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12848358.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!