一.概览
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
通俗来说,回溯法可以理解为通过选择不同的岔路口寻找目的地,一个岔路口一个岔路口的去尝试找到目的地。如果走错了路,继续返回来找到岔路口的另一条路,直到找到目的地。
二.基本思想
在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。
(1) 若使用回溯法求解任意一个解时,只要搜索到问题的一个解就可以结束。
(2) 若使用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索完才结束。
三.解题步骤
(1) 针对问题确定解空间;
首先应该明确定义问题的解空间,解空间至少包含问题的一个解。
(2) 确定结点的扩展搜索规则;
(3) 以深度优先搜索解空间,并在解空间中使用剪枝函数避免无效搜索。
四.常用的剪枝函数
(1) 用约束函数在扩展结点处剪去不满足约束的子树;
(2) 用限界函数剪去得不到最优解的子树;
回溯法对解空间做深度优先搜索时,有递归回溯和迭代回溯(非递归)两种方法,但一般情况下用递归方法实现回溯法。
五.实例:八皇后问题
在8X8格的国际象棋上摆放八个皇后(棋子),使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,求出一种有多少种摆法。
解题思路:
我们首先将问题简化为四皇后问题,并用回溯法来找到他们的解。目的是在4x4的棋盘上,使得4个皇后不能在同行同列以及同斜线上。
首先尝试将皇后放入第一个格子,被涂黑的地方是不能放皇后
第二行的皇后只能放在第三格或第四格,比方我们放第三格,则:
可以看到再难以放下第三个皇后,此时我们就要用到回溯算法了。我们把第二个皇后更改位置,此时我们能放下第三枚皇后了。
虽然是能放置第三个皇后,但是第四个皇后又无路可走了。返回上层调用(3号皇后),而3号也别无可去,继续回溯上层调用(2号),2号已然无路可去,继续回溯上层(1号),于是1号皇后改变位置如下,继续回溯。
上述就是回溯算法的过程,根据这个算法,最终能够把四位皇后放在4x4的棋盘里。也能用同样的方法解决了八皇后问题甚至N皇后问题。
六.N皇后问题伪代码
place_queen(row):
for 第row行的各列col:
if 位置(row,col)可以放置皇后:
在位置(row,col)放置一个皇后
if (row<9):
place_queen(row+1) # 递归
else:
成功
else
将位置(row,col)上的皇后取走,尝试下一列的位置 # 回溯
END
往期回顾