[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];
分类:
题目总结 / 2025. 1~3月
, 题目总结
标签:
动态规划
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步