题目:
Petya遇到了一个关于括号序列的问题: 给定一个字符串S,它代表着正确的括号序列,即(“(”)与 (“)”)是匹配的。例如:“(())()” 和 “()”是正确的,“)()”与“(()”则不是正确的。 在正确的括号序列中,一个左边的括号一定是匹配一个右边的括号(反之亦然)。例如,在下图中,第 3 个括号匹配第 6 个括号,第 4 个括号匹配第 5 个括号。
现在你需要对一个正确的括号序列做涂色操作,严格满足以下三个条件:
1、每个括号要么不涂色,要么涂红色,要么涂蓝色。
2、一对匹配的括号需要且只能将其中一个涂色。
3、相邻的括号不能涂上同一种颜色(但是可以都不涂颜色)。
求:给整个括号序列涂上颜色的方案数,答案可能比较大,对 1000000007 取模。
输入1:
(())
输出1:
12
输入2:
(()())
输出2:
40
输入3:
()
输出3:
4
题解:
首先由于是括号,我们需要知道它的左括号下标及右括号下标,存入数组方便后面用,方法是用栈,详细见代码:
void p() {
for(int i = 0;i < n; i++) {
if(a[i] == '(') {
s.push(i);//右括号输入进去
}
else{
b[i] = s.top();//遇到对应左括号弹出,再对下标保存
b[s.top()] = i;
s.pop();
}
}
return;
}
首先这道题的状态很不一样,令dp[i][j][k][l]为i括号取k种类颜色,和j括号取l种类颜色的方案总数。dp[i][j][k][l]应等于:
1.i+1==j(i括号与j括号相邻)
取法为一个无色一个颜色二选一
dp[i][j][1][0] = 1;
dp[i][j][0][1] = 1;
dp[i][j][2][0] = 1;
dp[i][j][0][2] = 1;
2.若b[i] == j(当i括号与j括号对应时):
首先求得元区间dp[i + 1][j - 1][k][l]的方案数, 用来求一个无色,一个随便取方式比如:dp[i][j][0][1],再加上dp[i + 1][j - 1][k][l] (注意l不能为1,因为若为1,则j-1号位为一号颜色,而j号位又是一号颜色所以相邻两个重复,舍去),其它三个完全同理思考,见代码:
if(j != 1) {
dp[qi][zhong][0][1] += dp[qi + 1][zhong - 1][i][j];
dp[qi][zhong][0][1] %= mod