回溯法有“通用的解题法”之称,用它可以系统地搜索一个问题的所有解或任一解。
回溯法是一个既带有系统性又带有跳跃性的搜索算法。
它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按照深度优先的策略进行搜索。
回溯法在用来求问题的所有解时要回溯到根,且根结点的所有子树都已被搜索遍才结束;而用来求问题的任一解时,只要搜索到问题的一个解就可以结束。
适用于解一些组合数较大的问题。
(一)回溯法的算法框架
1. 问题的解空间
在应用回溯法解问题时,首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。
定义了问题的解空间后,还应将解空间很好地组织起来,使得用回溯法能方便地搜索整个解空间,通常将解空间表示为树或图的形式。
2. 回溯法的基本思想
在确定了解空间的组织结构后,回溯法从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。
回溯的步骤:
- 开始结点成为一个活结点,同时也成为当前的扩展结点。
- 在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。
- 如果在当前扩展结点处不能再向纵深方向移动,则当前的扩展结点就成为死结点。此时,往回移动(回溯)至最近的一个活结点处,并使这个结点成为当前的扩展结点。
- 以这种工作方式递归地在解空间中搜索,直到找到所要求的解或解空间中已无活结点时为止。
3. 回溯法的算法框架
回溯法的算法框架有非递归和递归两种:
- 非递归方式
- 递归方式
4. 回溯法的限界函数
由于问题的解空间很大,为了有效地搜索,需要在搜索的过程中对某些结点进行剪枝,而对哪些结点进行剪枝,需要设计限界函数来判断。
设计限界函数的通用指导原则是尽可能多和尽可能早地“杀掉”不可能产生最优解的活结点。
(二)回溯法的典型实例
典型案例包括:背包问题,n
皇后问题。
n
皇后问题来源于国际象棋的一个问题。n
皇后问题要求在一个n X n
格的棋盘上放置n
个皇后,使得它们彼此不受攻击。按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一条斜线上的其他任何棋子。因此,n
皇后问题等价于要求在一个n X n
格的棋盘上放置n
个皇后,使得任何两个皇后不能被放在同一行或同一列或同一条斜线上。