Coloring Brackets[*1900] [区间DP] [DFS]
Coloring Brackets[*1900] [区间DP] [DFS]
三个要求
- 一个括号可以染成红色、蓝色或者不染色。
- 一对匹配的括号需要且只能将其中一个染色。
- 相邻两个括号颜色不能相同(但都可以不染色)。
遇到括号配对我们可以用stack来存储配对
数据结构的栈和队列应该刚讲了
然后可以用一个match数组来存储配对的下标
动态规划的关键就是一个大问题可以划分成几个不干扰的子问题
最后再进行合并
显然这个题的子问题可以划分成更小的可以配对的序列
这就可以依赖于刚才的match数组来实现
我们的动态转移方程中还需要携带状态
我们应该携带什么状态呢?
回头再看题目中的三个条件
显然我们可以携带边界的颜色来进行判断
将不染色 红色蓝色映射成0 1 2
由此便可以推出状态转移方程
因为子区间的划分是无序的
因此可以用DFS划分解决这道问题
key code
int n,m;
const int maxn=710;
const int mod=1e9+7;
char s[maxn];
int dp[maxn][maxn][3][3];
int match[maxn];
stack<int>S;
void dfs(int l,int r){
if(l+1==r){
dp[l][r][0][1]=
dp[l][r][0][2]=
dp[l][r][1][0]=
dp[l][r][2][0]=1;
}
else if(match[l]==r){
dfs(l+1,r-1);
fup(i,0,2)fup(j,0,2){
if(j!=1)(dp[l][r][0][1]+=dp[l+1][r-1][i][j])%=mod;
if(j!=2)(dp[l][r][0][2]+=dp[l+1][r-1][i][j])%=mod;
if(i!=1)(dp[l][r][1][0]+=dp[l+1][r-1][i][j])%=mod;
if(i!=2)(dp[l][r][2][0]+=dp[l+1][r-1][i][j])%=mod;
}
}
else{
dfs(l,match[l]);
dfs(match[l]+1,r);
fup(i,0,2)
fup(j,0,2)
fup(p,0,2)
fup(q,0,2)
if(j!=p||(j==p&&j!=1&&j!=2))
(dp[l][r][i][q]+=dp[l][match[l]][i][j]*dp[match[l]+1][r][p][q])%=mod;
}
}
void solve(){
//try it again.
cin>>s;
n=strlen(s);
up(0,n-1){
if(s[o]=='(')S.push(o);
else match[S.top()]=o,match[o]=S.top(),S.pop();
}
dfs(0,n-1);
int ans=0;
fup(i,0,2){
fup(j,0,2){
(ans+=dp[0][n-1][i][j])%=mod;
}
}
cout<<ans<<endl;
}

浙公网安备 33010602011771号