Coloring Brackets(区间dp-不错的题)

https://codeforces.com/contest/149/problem/D

题意: 给一匹配的括号序列,要求每对括号恰有一个被染成蓝或红色,要求相邻的括号不同色,求方案数

思路:

  • 首先考虑到每次搜的一个连续区间需要是合法的括号匹配。所以我开始想着直接把每一个子串的合理位置存下来。但是实际上最长串的每个合理位置都是固定的。因此开始括号匹配存下来即可
  • 然后由于要求是合法子串,不方便递推,dfs记忆化搜索更加方便。考虑dfs
  • dfs的过程中把判断当前子串是否合法写成函数,更加简洁明了。
  • 考虑当前的l和r是不是一个对应的匹配,是的话直接搜(l+1,r-1),条件用check()函数做
  • 考虑当前的l和r不是一个对应的匹配,那么就找到l的匹配或者r的匹配,都可以。继续搜并把答案乘起来。 比如( …) (…) (…) 这种状态,在dfs过程中实际上是被搜成(…)[ (…) (…) ]的,左边搜出答案后,后边搜出两个括号的答案变成[]再和左边合并即可。

调了挺久的一个坑,开始把stack写成了stack,然后疯狂mle以为爆栈。最后调了半天爆了RE发现问题。

#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=710;
const int mod=1e9+7;
typedef long long LL;
inline LL read(){
    
    LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){
    
    if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){
    
    x=x*10+ch-48;ch=getchar();}
return x*f;}
LL rightt[maxn],ans=0;
LL dp[maxn][maxn][3][3];
char s[maxn];
inline bool check(int l,int r,int p,int q){
    
    
    if(rightt[l]!=r) return 0;///还需要递归分开
    ///以下为两个是一对的情况
    if(p>0&&q>0) return 1;///两个都染色了
    if(p==0&&q==0) return 1;///两个都没染色
    return 0;
}
LL dfs(LL l,LL r,LL p,LL q){
    
    
    if(dp[l][r][p][q]) return dp[l][r][p][q];
    if(check(l,r,p,q)) return 0;///不合法直接返回0
    if(l+1==r){
    
    
        dp[l][r][p][q]=1;
        return 1;
    }
    if(rightt[l]==r){
    
    
        for(int j=0;j<3;j++){
    
    
            for(int k=0;k<3;k++){
    
    
                if(j>0&&j==p) continue;
                if(k>0&&k==q) continue;
                dp[l][r][p][q]=(dp[l][r][p][q]+dfs(l+1,r-1,j,k)%mod)%mod;
            }
        }
        return dp[l][r][p][q]%mod;
    }
    else{
    
    
        for(int j=0;j<3;j++){
    
    
            for(int k=0;k<3;k++){
    
    
                if(j==k&&j>0) continue;
                if(check(l,rightt[l],p,j)||check(rightt[l]+1,r,k,q)) continue;
                dp[l][r][p][q]=(dp[l][r][p][q]+dfs(l,rightt[l],p,j)*dfs(rightt[l]+1,r,k,q)%mod)%mod;
            }
        }
        return dp[l][r][p][q]%mod;
    }
}
int main(void){
    
    
    scanf("%s",s+1);LL n=strlen(s+1);
    stack<LL>st;
    st.push(1);
    for(int i=2;i<=n;i++){
    
    
        if(s[i]=='(') st.push(i);
        else{
    
    
            rightt[st.top()]=i;
            st.pop();
        }
    }
    memset(dp,0,sizeof(dp));
    for(int i=0;i<3;i++){
    
    
        for(int j=0;j<3;j++){
    
    
            ans=(ans+dfs(1,n,i,j)%mod)%mod;
            ///debug(ans);
        }
    }
    printf("%lld\n",ans);
   	return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/121255643