目录
什么是回溯算法?
基本概念
回溯是一种用于寻找某些计算问题的全部(或部分)解的通用算法。
回溯算法的核心思想是逐步构建候选解,如果发现当前构建的候选解不符合要求,就回溯到上一步撤销当前选择,重新选择其他方案,继续构建候选解。这个过程就像是在树形结构中向下逐步探索,到达某个节点时,如果发现无法继续向下搜索,就返回到上一层节点,继续从其他子节点开始探索。
回溯算法通常使用递归实现,每一次递归都对一个子问题进行求解,直到求得最终解或无法继续求解后回溯到上一步。为了避免重复搜索同一个状态,回溯算法通常需要使用状态重置或剪枝等技巧对搜索空间进行优化。
咳咳,说了这么多的理论,其实我的脑子都有点浆糊了,也许能动手的情况下还是少动口是一种好习惯。
下面给大家举例一个生活中最最常见的例子来阐述下这个美丽动人的回溯算法。
示例认知
下面这张图一眼看过去,它是一个有3条路的迷宫。你想知道它是否有出口(为了精确起见,使用你双眼观察法比回溯更有效)。这就是迷宫:
这3条路究竟哪一条才是通往出口的路,或者是没有任何一条可以通往出口呢?我们使用回溯法,将每一条路都尝试走下,当所有的路都走完时,真相就会无所遁形!
上图通过遍历所有的可行路径,当某路不通时返回此路的源点,然后继续搜索可用的路,直到找到正确的出口。
我们的想法是,我们可以使用递归一步一步地构建解决方案;如果在这个过程中我们意识到这将不是一个有效的解决方案,那么我们停止计算该解决方案,并返回到前面的步骤(回溯)。在迷宫的情况下,当我们处于死胡同时,我们被迫走回头路,但在其它情况下,我们可能会在到达之前意识到,我们正在走向一个无效的(或不好的)解决方案。
什么时候可以使用回溯算法?
当我们遇到下面的几种类型时,就可以使用回溯算法来解决
- 决策问题--在这个问题中,我们寻找一个可行的解决方案。
- 优化问题--在这个问题中,我们寻找最优解。
- 枚举问题--在这个问题中,我们找到所有可行的解决方案。
我们平时最为常见的就是解决组合问题、排列问题、迷宫问题、数独问题、四皇后问题、无向图节点路径问题。
然而,它并不是一个优化的算法,因为它的核心使用了暴力方法。因此,如果时间复杂性受到限制,建议使用其他可能更适合这种情况的优化算法。
回溯算法经典应用-无向图两节点之间路径
问题描述
下面是一张无向图,现在我们要计算出从A到E两个节点之前所有可行的路径。需要注意的是在计算有向图中两个顶点之间存在的路时,路径不包含循环,原因很简单,因为一个循环包含无限数量的路径。
这个问题可以使用回溯来解决,即选择一条路径并开始在其上行走,检查它是否引导我们到达目的地顶点,然后计算路径并回溯到另一条路径。如果路径不指向目标顶点,则丢弃该路径。这种类型的图遍历称为回溯。
回溯过程
上图的回溯过程如下所示(红色顶点为源顶点,淡蓝色顶点为目的顶点,其余为中间路径或丢弃路径)
为什么这个解决方案不适用于包含圈的图?下面的这张图为改造后包含循环的图。