第三章 回溯
1、回溯的来源
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。
在生活实际中有些问题是不能用数学公式去解决的,它需要通过一个过程,此过程要经过若干个步骤才能完成,每一个步骤又分为若干种可能;同时,为了完成任务,还必须遵守一些规则,但这些规则无法用数学公式表示。对于这样一类问题,一般采用搜索的方法来解决。
而且,寻找问题的解的一种可靠的方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到所需要的解。理论上,当候选解数量有限并且通过检查所有或部分候选解能够得到所需解时,上述方法是可行的。不过,在实际应用中,很少使用这种方法,因为候选解的数量通常都非常大(比如指数级,甚至是大数阶乘),即便采用最快的计算机也只能解决规模很小的问题。
对候选解进行系统检查的方法有多种,其中回溯法是典型的一种。
例如走迷宫问题。
如下:
(幽默一下,另一个走迷宫问题:老鼠走迷宫)
2、回溯的概念
现在由上面走迷宫的思路,引出回溯法所特有的思想方式。
回溯法就是搜索算法中的一种控制策略,它能够解决许多搜索中问题。回溯算法的基本思想是:每次只构造解的一个分量,然后按照下面的方法来评估这个部分构造解。如果一个部分构造解可以进一步构造而不会违反问题的约束,那么我们就接受对解的下一个分量所作的第一个合法选择。如果无法对下一个分量进行合法的选择,就不必再对剩下的任何分量做任何选择了。在这种情况下,该算法进行回溯,把部分构造解的最后一个分量替换为它的下一个选择。
简而言之,就是:“从一条路往前走,能进则进,不能进则退回来,换一条路再试”。
3、解决问题的一般步骤
用回溯算法解决问题的一般步骤为:
a. 定义一个解空间,它包含问题的解。
b.利用适于搜索的方法组织解空间。
c.利用深度优先法搜索解空间。
d.利用限界函数避免移动到不可能产生解的子空间。
问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。
回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。
这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。
4、举例说明
(1)上文提到的迷宫问题
这是典型的应用“回溯法”解决的问题。
(2)旅行商问题
一个推销员要到几个城市去办理业务,城市间里程数已知,问题的提法是:从某个城市出发,每个城市只允许访问一次,最后又回到原来的城市,求一条最短距离的路径。
下图表示出五城市旅行商问题的地图,求从A出发经B、C、D、E再回到A的最短路径。
解决方法类似于上面的“走迷宫算法”。
4、回溯小结
优点:适合在解空间非常大的情况下使用,节省时间、精力,找到最终结果的效率高,需要的运算时间、储存空间也小
缺点:最终找到的只是所有解中的一个近似最优解(也有可能是最有解,但不一定),为什么这么说呢,因为它在处理过程中并不能把所有的情况都考虑到(这也是它的优点所在),所以最终的解不一定是最优的。如前面的走迷宫算法,假如这个迷宫存在两条通路,那么,这个算法只能找出其中的一条通路。
解决方法:在使用本算法前,先考虑到这个问题的求解是不是规模很大,这个问题对解的要求是不是很严格。若问题规模很大,或者对解的要求不严格(比如,只需找出一个解即可),那么,再使用本算法。