[ZOJ2604] Little Brackets

Little Brackets

题意

给定序列长度 \(2n\), 求「深度」为 \(k\) 的合法括号序列有多少个. 其中「深度」定义为序列前缀中左括号数量与右括号数量之差的最大值.

算法

动态规划.

思路

我们考虑求一个前缀. 令 \(f_{i, j}\) 表示长度为 \(2i\) 的合法括号序列中深度不超过 \(j\) 的序列数量, 这样我们最终所求的答案便成了 \(f_{n, k} - f_{n, k - 1}\).

现在来思考怎么转移. 通过观察可以发现, 每一个合法的括号序列一定可以写成形如 \((\textrm{X})\textrm{Y}\), 其中 \(\rm{X, Y}\) 均为合法括号序列 (可以为空). 不妨设 \(2k\)\((\rm{X})\) 的长度, 那么 \(\rm{Y}\) 的长度即为 \(2(i - k)\), \(\rm{X}\) 的长度为 \(2(k - 1)\). 由于整个括号序列的深度小于等于 \(j\), \(\rm{Y}\) 的深度也应当小于等于 \(j\), 所以 \(\rm{Y}\) 处的转移方程为 \(f_{i - k, j}\). 同理可得, \(\rm{X}\) 处的转移方程为 \(f_{k - 1, j - 1}\), 个人理解 \((j - 1)\) 是由于外层括号 \(()\) 可能会有贡献导致的.

所以总体的转移方程为 \(\displaystyle f_{i, j} = \sum_{k = 1}^i f_{k - 1, j - 1} \times f_{i - k, j}\)​, 预处理出即可.

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
for (int i = 0; i <= 50; ++i) f[0][i] = 1; for (int i = 1; i <= 50; ++i) for (int j = 1; j <= 50; ++j) for (int k = 1; k <= i; ++k) f[i][j] += f[k - 1][j - 1] * f[i - k][j];
posted @   Steven1013  阅读(15)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开