1001(括号序列, 区间dp)
题目
题目描述
给出一个长度为$n$的括号序列$A$, 括号有$m$种(类似于大小中括号, 只能同种括号之间匹配)
其中$A_i > 0$表示位置$i$上是一个种类为$A_i$的左括号, $A_i < 0$表示位置$i$上是一个种类为$|A_i|$的右括号, $A_i = 0$表示此处的括号可以由你指定种类和左右
问有多少种指定方案使得这个序列是一个合法的括号序列
数据范围
多组数据, $T \leq 20$
$1 \leq n \leq 500, 1 \leq m < 10^9 + 7$
$|A_i| \leq m$
时间限制
$3000ms$
题解
首先很容易想到区间$dp$, 比赛时我的第一反应也是这样, 但是一想数据范围是$T \times n^3$, 达到了$10^9$级别, 肯定过不了, 就没接着往下想, 但是事实证明其实能过
那区间$dp$思路就比较显然了, 设$g[l][r]$表示区间$[l, r]$的合法方案数量, 区间$[l, r]$至少能被分成两段合法的括号序列(如果$A_l$和$A_r$进行了匹配, 那么我们认为这两段是空集和$[l, r]$)
那我们是不是只要枚举一下这两段的分割点然后统计答案就可以了
这样是不对的, 因为有算重的方案, 下面举个例子
()()()
对于这个序列而言, 两段可以是$[1, 2], [3, 6]$也可以是$[1, 4], [5, 6]$, 但这其实是一种, 所以上述转移方程是不对的
那我们应该怎么转移呢? 还是区间$[l, r]$至少能被分成两段这个思路, 只不过我们强制让$A_r$和$A_{k + 1}$进行匹配, 这样就不会重复了, 设$f[i][j]$表示$A_i$和$A_j$匹配的限制下区间$[l, r]$的合法方案数量, 那么有
设$mul$为$A_l$和$A_r$匹配的方案数, 那么有
$dp$时当前处理区间长度为最外层循环$len$, 内层为左端点$l$, 处理时先处理$f$处理$g$(因为计算$g$时需要当前$len$层的$f$, 而计算$f$需要的是上一层$len - 1$的$g$)
代码
1 |
|