欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Coloring Brackets | 区间计数dp、多条件限制

程序员文章站 2022-06-24 10:02:52
题目链接:https://codeforces.com/contest/149/problem/D题目大意:给出一个合法的括号序列,下面你会给这个括号序列涂色,涂色时要满足下面三个条件:1.每对匹配的括号必须有且只有一个被染色2.相邻括号间染色不可以相同3.每个括号染色的状态只能是 染红,染蓝,不染询问合法的染色方案数题目思路:确实是一个好题括号匹配必然和区间有关系考虑区间dp[l][r]dp[l][r]代表区间[l,r]的合法染色方案数但是无法处理相邻颜色....

题目链接:https://codeforces.com/contest/149/problem/D

题目大意:

给出一个合法的括号序列,下面你会给这个括号序列涂色,涂色时要满足下面三个条件:

1.每对匹配的括号必须有且只有一个被染色

2.相邻括号间染色不可以相同

3.每个括号染色的状态只能是 染红,染蓝,不染

询问合法的染色方案数

题目思路:

确实是一个好题

括号匹配必然和区间有关系

考虑区间dp[l][r]

dp[l][r]代表区间[l,r]的合法染色方案数 

但是无法处理相邻颜色是否相同的情况,所以肯定要新增一维:

dp[l][r][x][y]代表区间[l,r]左端点染色[x],右端点染色[y]的合法染色方案数

那么由于有括号匹配

  • 如果当前l 与 r匹配,那么肯定只有4种方案,01、02、10、20,那么就直接可以用[l+1,r-1]的合法方案数考虑合法转移
  • 如果当前l 与 r不匹配,那么看一下l的匹配位置在哪,假设匹配位置是pos,那么处理完[l,pos]与[pos+1,r]的方案数之后,便可以根据乘法原理进行合法的转移

好题..

Code:

/*** keep hungry and calm CoolGuang!***/
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll dp[705][705][3][3];
int R[maxn];
int st[maxn];
int dx[4] = {0,0,1,2};
int dy[4] = {1,2,0,0};
char s[maxn];
void dfs(int l,int r){
    if(r-l+1 == 2){///递归方式导致len = 2 只能是单括号匹配
        dp[l][r][0][1] = dp[l][r][0][2] = dp[l][r][2][0] = dp[l][r][1][0] = 1;///匹配
        return ;
    }
    if(R[l] == r){///如果当前匹配
        ///那么两端颜色的选择与[l+1,r-1]有关
        dfs(l+1,r-1);
        for(int i=0;i<3;i++){
            for(int k=0;k<3;k++){
                for(int j=0;j<4;j++){
                    int idx = dx[j],idy = dy[j];
                    if((idx!=0 && idx == i)) continue;
                    if((idy!=0 && idy == k)) continue;
                    dp[l][r][idx][idy] = (dp[l][r][idx][idy] +dp[l+1][r-1][i][k])%mod;
                }
            }
        }
    }
    else{
        int temp = R[l];
        dfs(l,temp);
        dfs(temp+1,r);
        for(int i=0;i<3;i++){
            for(int k=0;k<3;k++){
                for(int x=0;x<3;x++){
                    for(int y=0;y<3;y++){
                        if(k!=0 && k==x) continue;
                        dp[l][r][i][y] = (dp[l][r][i][y] + dp[l][temp][i][k] * dp[temp+1][r][x][y])%mod;
                    }
                }
            }
        }
    }
}
int main(){
    scanf("%s",s+1);
    n = strlen(s+1);
    int top = 0;
    for(int i=1;i<=n;i++){
        if(s[i] == '(') st[++top] = i;
        else R[st[top--]] = i;
    }
    dfs(1,n);
    ll ans = 0;
    for(int i=0;i<3;i++){
        for(int k=0;k<3;k++){
            ans = (ans + dp[1][n][i][k])%mod;
        }
    }
    printf("%lld\n",ans);
    return 0;
}
/***

***/

 

本文地址:https://blog.csdn.net/qq_43857314/article/details/110182932