• CF149D Coloring Brackets


    DP神题。。。
    (dp[i][j][0/1/2][0/1/2])表示([i,j])这个区间内端点取不染色/染红色/染蓝色三个状态然后转移。一个新(trick)就是这里的转移只要考虑这个区间内的串是合法的就可以了

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    #define R register
    #define LL long long
    const int inf = 0x3f3f3f3f;
    const int N = 700 + 5;
    const int P = 1e9 + 7;
    
    inline int read() {
    	char a = getchar(); int x = 0,f = 1;
    	for(; a > '9' || a < '0'; a = getchar()) if(a == '-') f = -1;
    	for(; a >= '0' && a <= '9' ;a = getchar()) x = x * 10 + a - '0';
    	return x * f;
    }
    
    int n;
    char s[N];
    int f[N][N][3][3]; // 700 * 700 * 3 * 3 
    int nxt[N];
    int st[N], top;
    
    inline void dp(int l, int r) {
    	if(l + 1 == r) {
    		f[l][r][0][1] = f[l][r][1][0] = f[l][r][2][0] = f[l][r][0][2] = 1;
    		return ;
    	}
    	if(nxt[l] == r) {
    		dp(l + 1, r - 1);
    		for(R int i = 0; i < 3; i++) 
    			for(R int j = 0; j < 3; j++) {
    				if(j != 1) f[l][r][0][1] = (f[l][r][0][1] + f[l + 1][r - 1][i][j]) % P;
    				if(i != 1) f[l][r][1][0] = (f[l][r][1][0] + f[l + 1][r - 1][i][j]) % P;
    				if(j != 2) f[l][r][0][2] = (f[l][r][0][2] + f[l + 1][r - 1][i][j]) % P;
    				if(i != 2) f[l][r][2][0] = (f[l][r][2][0] + f[l + 1][r - 1][i][j]) % P;
    			}
    		return ;
    	}
    	else {
    		int m = nxt[l];
    		dp(l, m);
    		dp(m + 1, r);
    		for(R int i = 0; i < 3; i++)
    			for(R int j = 0; j < 3; j++)
    				for(R int u = 0; u < 3; u++)
    					for(R int v = 0 ; v < 3 ; v++ ) {
    						if(u == v && u != 0) continue;
    						f[l][r][i][j] = (f[l][r][i][j] + (1LL * f[l][m][i][u] * f[m + 1][r][v][j]) % P ) % P;
    					}
    	}
    }
    
    int main() {
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	scanf("%s", s + 1);
    	n = strlen(s + 1);
    	for(R int i = 1; i <= n; i++) {
    		if(s[i] == '(') st[++top] = i;
    		else {
    			nxt[st[top]] = i;
    			top--;
    		}
    	}
    	dp(1, n);
    	int ans = 0;
    	for(R int i = 0; i < 3; i++ )
    		for(R int j = 0; j < 3; j++)
    			ans = ( ans + f[1][n][i][j] ) % P;
    	printf("%d
    ", ans);
    	return 0;	
    }
    
  • 相关阅读:
    【SQL Server学习笔记】Service Broker创建异步的、数据驱动的消息应用程序
    记录几句不错的话
    DBA最缺的不是技术
    小数点引起的数据类型转换问题
    hdu 3062 2SAT最基础题
    POJ 1679 判断最小生成树是否唯一
    POJ 1459 构图+最大流(Edmond_karp模版)
    POJ 3522 最大边与最小边差值最小的生成树
    POJ 1659 根据度序列构图
    POJ 1273 求最大流(Edmond_karp模板题)
  • 原文地址:https://www.cnblogs.com/clover4/p/12896265.html
Copyright © 2020-2023  润新知