算法浅谈之迭代加深
一、迭代加深概念
迭代加深英文简写:\(\large iddfs\),一个具有深度限制的深度优先搜索算法会不断重复地运行,并且同时放宽对于搜索深度的限制,直到找到目标状态。
二、理解与感悟
优化搜索的一种方法,可以看成把广搜和深搜的优点结合在一起的算法,但是空间比广搜要小的多。(一般在求最少步数类似的题目中可以运用)算法流程如下:
- 枚举每次搜索的深度
- 如果当前深度超过了指定的深度,\(return\)
- 如果当前已经找到了答案,便可直接返回解,省略后面无用的搜索。
三、知识精讲
指导搜索的朋友们都知道,在\(dfs\)(深度优先搜索)中,我们可以用一棵树形象的代表搜索的过程;
上面两张\(dfs\)过程图,红色的点代表我要搜索的答案,我们的程序是从最左边的那一枝连环地往下搜索,有多深搜多深,那么问题来了,这样猛搜如果太深会不会导致程序爆炸呢,而且更有可能白白浪费时间,这就不是爆搜了,这是傻搜;如右图,对于红框中的节点,显然是浪费的;如果我们有一种方法可以避免搜这些点······
好,这就引出了我们今天的主题,迭代加深;我们可以从小到大限制搜索的深度,如果在当前深度限制下搜不到答案,就把深度限制增加,重新进行一次搜索,这就是迭代加深思想;所谓“迭代”,就是以上一次的结果为基础,重复执行以逼近答案的意思;迭代加深的搜索显然不同于深搜,但和广搜也是有很大区别的;
仔细想一想,灵魂还是深搜的,只不过是让深搜的那棵树,慢慢长~,避免跳过了答案所在的浅层,直接干到很深很深的层次上了;
其实我说道这种程度,大家应该都能懂了,不过为了更完美,我还是要把整个过程模拟一遍,小的给各位客官上图:
图三,深度为\(1\),搜索失败,图四深度为\(2\),搜索失败,图五,深度为三,任务完成;
怎么样,是不是清楚很多了呢,一下子省了\(N\)多层;
(其实,这种手段在我们小组里成为噶韭菜);
这种算法看起来好高级~不过它还有一个弱点,那就是可能会重复搜索浅层的节点,但是那和超级深的搜索相比起来,实在是不算什么,规模并不算大,而且代码很好写,平时的搜索,我们当然是可以接受的啦!
此外,还是希望各位客官能够 清楚迭代加深搜索用在什么地方,当搜索树规模随着层次深入增长很快,并且我们能够确保答案在一个较浅层的节点时,就可以采用迭代加深的\(dfs\)来解决问题。我们 可以通过估算来确定,有些题目会有明确的暗示,如果\(n\)步内没有结果就输出\(-1\);
这个算法我就不出代码了,因为马上就要发一道题解,用的就是这个算法;
但还是跟大家说一个比较有意思的例题:\(POJ2248\) \(Addition\) \(Chains\);大家可以到\(poj\)去看一下;
最后,我在这里提一下,这个解说部分参考和引用了李煜东学长的《算法竞赛进阶指南》一书,并且以后的博文都有可能参考这本书,也为各个学信息奥赛的同志们推荐这本书,李煜东学长写得很用心,例题也十分经典,非常适合竞赛使用。
四、一般套路
int depth = 0;
while (!dfs(depth, 0, 0, 0)) depth++;
而搜索时也不要忘了剪枝
if (ul + dl > depth) return false;
五、疑惑问题
每次都枚举深度,深度不断++,而每次又从头开始进行搜索,那会有很多进行重复搜索的呀?
解释:
因为深度越大,结点的数目也就越多,耗费的时间是呈几何级增长的,重复搜索的部分时间基本可忽略不计。