IDA*
本页面将简要介绍 IDA * 算法。
定义
IDA * 为采用了迭代加深算法的 A * 算法。
优点
由于 IDA * 改成了深度优先的方式,相对于 A * 算法,它的优点如下:
- 不需要判重,不需要排序,利于深度剪枝。
- 空间需求减少:每个深度下实际上是一个深度优先搜索,不过深度有限制,使用 DFS 可以减小空间消耗。
缺点
- 重复搜索:即使前后两次搜索相差微小,回溯过程中每次深度变大都要再次从头搜索。
实现(伪代码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
例题
埃及分数
在古埃及,人们使用单位分数的和(即 \(\frac{1}{a}\),\(a\in\mathbb{N}^*\))表示一切有理数。例如,\(\frac{2}{3}=\frac{1}{2}+\frac{1}{6}\),但不允许 \(\frac{2}{3}=\frac{1}{3}+\frac{1}{3}\),因为在加数中不允许有相同的。
对于一个分数 \(\frac{a}{b}\),表示方法有很多种,其中加数少的比加数多的好,如果加数个数相同,则最小的分数越大越好。例如,\(\frac{19}{45}=\frac{1}{5}+\frac{1}{6}+\frac{1}{18}\) 是最优方案。
输入整数 \(a,b\)(\(0<a<b<500\)),试编程计算最佳表达式。
样例输入:
1 |
|
样例输出:
1 |
|
解题思路
这道题目理论上可以用回溯法求解,但是解答树会非常「恐怖」——不仅深度没有明显的上界,而且加数的选择理论上也是无限的。换句话说,如果用宽度优先遍历,连一层都扩展不完,因为每一层都是 无限大 的。
解决方案是采用迭代加深搜索:从小到大枚举深度上限 \(\textit{maxd}\),每次执行只考虑深度不超过 \(\textit{maxd}\) 的节点。这样,只要解的深度有限,则一定可以在有限时间内枚举到。
深度上限 \(\mathit{maxd}\) 还可以用来 剪枝。按照分母递增的顺序来进行扩展,如果扩展到 i 层时,前 \(i\) 个分数之和为 \(\frac{c}{d}\),而第 \(i\) 个分数为 \(\frac{1}{e}\),则接下来至少还需要 \(\frac{\frac{a}{b}-\frac{c}{d}}{\frac{1}{e}}\) 个分数,总和才能达到 \(\frac{a}{b}\)。例如,当前搜索到 \(\frac{19}{45}=\frac{1}{5}+\frac{1}{100}+\cdots\),则后面的分数每个最大为 \(\frac{1}{101}\),至少需要 \(\frac{\frac{19}{45}-\frac{1}{5}}{\frac{1}{101}}=23\) 项总和才能达到 \(\frac{19}{45}\),因此前 \(22\) 次迭代是根本不会考虑这棵子树的。这里的关键在于:可以估计至少还要多少步才能出解。
注意,这里使用 至少 一词表示估计都是乐观的。形式化地,设深度上限为 \(\textit{maxd}\),当前结点 \(n\) 的深度为 \(g(n)\),乐观估价函数为 \(h(n)\),则当 \(g(n)+h(n)>\textit{maxd}\) 时应该剪枝。这样的算法就是 IDA*。当然,在实战中不需要严格地在代码里写出 \(g(n)\) 和 \(h(n)\),只需要像刚才那样设计出乐观估价函数,想清楚在什么情况下不可能在当前的深度限制下出解即可。
如果可以设计出一个乐观估价函数,预测从当前结点至少还需要扩展几层结点才有可能得到解,则迭代加深搜索变成了 IDA * 算法。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
|
习题
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用