CodeForces 149D-Coloring Brackets(区间dp 的好题)

来源:互联网 发布:消防安全知识网络大赛 编辑:程序博客网 时间:2024/06/14 08:30

题意:
给一个给定括号序列,给该括号上色,上色有三个要求

1、只有三种上色方案,不上色,上红色,上蓝色

2、每对括号必须只能给其中的一个上色

3、相邻的两个不能上同色,可以都不上色

求0-len-1这一区间内有多少种上色方案

思路:括号匹配问题是典型区间dp问题,这题在此基础上改编增加颜色的规定,于是我需要多定义两层设dp[i][j][l][r]表示:从i到j这个括号序列i位置为l颜色,j位置为r颜色的状态下的总共上色方案。可以规定0为不上色,1为红色,2为蓝色,这样dp[len][len][3][3]状态就定好了。
考虑括号串的匹配过程,都是嵌套的过程,于是我们可以递归的计数,首先得用栈扫一遍串,记载每个左右括号相对的匹配的位置。然后递归的搜索下去。
根据题意的规则,制定搜索的规则。
详见代码:

#include<bits/stdc++.h>using namespace std;char s[700+10];const int mod=1e9+7;int match[700+10],n;long long dp[700+10][700+10][3][3];stack<int>sta;void init(){  while(!sta.empty()) sta.pop();  for(int i=1;i<=n;i++){    if(s[i]=='(') sta.push(i);    else { match[i]=sta.top();match[sta.top()]=i;sta.pop();}  }}void dfs(int l,int r){   if(l+1==r){     dp[l][r][1][0]=1;dp[l][r][0][1]=1;//每一对括号只有有且只有一个括号有颜色的情况计数,其他为0     dp[l][r][2][0]=1;dp[l][r][0][2]=1;     return;   }   if(match[l]==r){      dfs(l+1,r-1);      for(int i=0;i<3;i++){        for(int j=0;j<3;j++){          if(i!=1) dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod;//保证相邻的不同颜色          if(i!=2) dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod;          if(j!=1) dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod;          if(j!=2) dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod;        }      }   }   else{     int p=match[l];     dfs(l,p);dfs(p+1,r);     for(int i=0;i<3;i++){        for(int j=0;j<3;j++){            for(int k=0;k<3;k++){               for(int q=0;q<3;q++){                  if(k!=q||k==0) dp[l][r][i][j]=(dp[l][r][i][j]+dp[l][p][i][k]*dp[p+1][r][q][j])%mod;//保证相邻的不同颜色,或者都不上色               }            }        }     }   }}int main(){   while(~scanf("%s",s+1)){      n=strlen(s+1);      init();      memset(dp,0,sizeof(dp));      dfs(1,n);      long long ans=0;      for(int i=0;i<3;i++){        for(int j=0;j<3;j++){          ans=(ans+dp[1][n][i][j])%mod;        }      }      printf("%lld\n",ans);   }}
1 0
原创粉丝点击