递推小测验
洛谷 P1096 Hanoi 双塔问题
思路
类比于传统的汉诺塔问题,我们会将前 \(2(n-2)\) 个圆盘从 \(A\) 柱移动到 \(B\) 柱上,将最大的两个圆盘从 \(A\) 柱移动到 \(C\) 柱上,再将 \(2(n-2)\) 个圆盘从 \(B\) 柱移动到 \(C\) 柱上。
令 \(f_i\) 表示将 \(2i\) 个圆盘移动完成的最小移动次数,那么 \(f_i = 2f_{i - 1} + 2\),初始状态 \(f_0 = 0\),目标状态 \(f_n\)。
由于题目数据范围 \(n \le 200\),而后一项是前一项至少两倍,因此需要使用高精度模拟递推过程。
时空复杂度
空间复杂度
存储高精度答案 \(O(n)\)。
时间复杂度
\(n\) 次递推,每次递推进行高精度计算 \(O(n)\),总时间复杂度 \(O(n^2)\)。
洛谷 P1464 Function
思路
递归,利用记忆化搜索优化时间复杂度。
时空复杂度
令 \(n\) 为递归函数三个参数的最大值。
空间复杂度
记忆化数组 \(O(n^3)\)。
时间复杂度
一共 \(O(n^3)\) 个状态,每个状态转移时间复杂度 \(O(1)\),总时间复杂度 \(O(n^3)\)。
洛谷 P1028 数的计算
-
先定好状态,找到转移(搞清楚初始状态、目标状态、非法状态),用暴搜实现。
-
如果状态转移存在拓扑序,从目标状态开始分治求解,利用记忆化搜索优化。
-
如果知道具体拓扑序,则用递推实现。
思路
思路 1
每次在序列左端加入一个数字,而当左端数字相同时继续往后能加的数字也是相同的,因此将状态设计为左端数字 \((i)\)。
初始状态为 \((n)\),目标状态为 \((1) \dots (n)\)。
每一次可以在左端加入 \(1 \sim \lfloor \frac{i}{2} \rfloor\) 这些数字,\((i)\) 转移到 \((1) \dots (\lfloor \frac{i}{2} \rfloor)\)。
拓扑序为左端数字从大到小的方向。
思路 2
考虑往序列右端加入数字,直到右端为 \(n\)。
状态为右端数字 \(i\),初始状态为 \((1) \sim (n)\),目标状态为 \((n)\)。
每一次在右端加入 \(2 * i \sim n\) 这些数字,\((i)\) 转移到 \((2 * i) \dots (n)\)。
拓扑序为右端数字从小到大的方向。
时空复杂度
空间复杂度
记录状态 \(O(n)\)。
时间复杂度
对于每个状态,需要 \(O(n)\) 的时间进行转移,总时间复杂度 \(O(n^2)\)。
洛谷 P1057 传球游戏
-
先定好状态,找到转移(搞清楚初始状态、目标状态、非法状态),用暴搜实现。
-
如果状态转移存在拓扑序,从目标状态开始分治求解,利用记忆化搜索优化。
-
如果知道具体拓扑序,则用递推实现。
思路
球传到谁的手中,以及传球次数,都是求解问题需要关注的部分。题目中所有人环形排列,应该使用 \(0 \sim n - 1\) 给人编号。
状态 \((i, j)\) 表示第 \(i\) 次传球传到 \(j\) 的手中,初始状态 \((0, 0)\),目标状态 \((m, 0)\)。
每一次传球传给左右两人,\((i, j)\) 转移到 \((i + 1, j_1)\) 和 \((i + 1, j_2)\),\(j_1, j_2\) 为 \(j\) 的左右两人。
观察发现,传球次数不断增大,转移是朝着 \(i\) 从小到大的方向进行的,因此拓扑序为 \(i\) 从小到大。
时空复杂度
空间复杂度
记录状态及其方案数 \(O(nm)\)。
时间复杂度
\(O(nm)\) 个状态,每个状态转移两次,总时间复杂度 \(O(nm)\)。