zoukankan      html  css  js  c++  java
  • CF149D Coloring Brackets

    给一个合法的括号序列。求满足以下条件的染色方案。
    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 << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    移动端 viewport设置
    js 数组去重
    常用排序算法之JavaScript实现
    当Table中td内容为空时,显示边框的办法
    html5标签
    CSS z-index 属性的使用方法和层级树的概念
    seajs第二节,seajs各模块依赖关系
    seajs第一节,seajs基本使用
    强大的矢量图形库:Raphael JS 中文帮助文档及教程
    apache日志轮转
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12848358.html
Copyright © 2011-2022 走看看