P1044. 模板题_栈
考点
- 卡特兰数
- 线性动态规划
题解
见思路
思路
卡特兰数
卡特兰数本身并不难理解,可以直接看这篇链接进行学习
这里提醒一下,在《深基》与《算法导论》中非法序列的个数为\(C_{2n}^{n-1}\),在上面的链接中则是\(C_{2n}^{n+1}\);但结果是一样的,只是角度不同
因为组合数本来就有这个性质: \[ C_{n}^{m}=C_{n}^{n-m} \] 故而本题可以直接按照卡特兰数的通项输出即可,不再赘述
递推
思路来源于kkksc03
假设i个元素一共有h[i]种出栈方式,那么要求的就是n个元素的出栈方式,即h[n]
n个元素下标为从1到n,每个元素都有可能是最后一个出栈的,即输出序列的最后一位
假设第k个数是最后一个出栈的,情况会是这样:
前面有k-1个数先入栈,然后出栈,即h[k-1]
第k个数入栈
n-k个数入栈,然后出栈,即h[n-k]
所以当第k个数是最后一个出栈时,情况共有h[k-1] * h[n-k]
种
那么就能得到递推式: \[ h\left( n \right) =h\left( 0 \right) \times h\left( n-1 \right) +h\left( 1 \right) \times h\left( n-2 \right) +...+h\left( n-1 \right) \times h\left( 0 \right) \]
\[ h\left( 0 \right) =h\left( 1 \right) =1 \]
这样就能写出极简代码了:
1 |
|
线性动态规划 记忆化搜索
以输出序列的元素个数qe,栈的元素个数st为状态分析对象,建立二维数组mem[qe][st]
根据栈的性质,要么从栈顶弹出一个元素给输出序列,要么就继续入栈新元素不弹出;易得状态转移方程如下:
\[
\underset{\text{栈顶弹出给输出序列}}{\underbrace{mem\left[ qe-1 \right]
\left[ st+1 \right]
}}+\underset{\text{入栈新元素不弹出}}{\underbrace{mem\left[ qe \right]
\left[ st-1 \right] }}\rightarrow mem\left[ qe \right] \left[ st \right]
\]
那么临界值呢?很显然,当输出序列qe为0的时候不可再分,此时令mem[qe][st] = 1
;如果越界的话令mem[qe][st] = 0
即可
1 |
|
线性动态规划 递推
将上面的递归改成迭代即可,不再赘述
1 |
|