回溯算法
1、简介
\quad \quad 回溯算法实际上是基于DFS(深度优先搜索)的一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。
DFS 和回溯算法区别
\quad \quad DFS 是一个劲的往某一个方向搜索,直到到达最底层,而回溯算法建立在 DFS 基础之上的,但不同的是在搜索过程中,达到结束条件后,恢复状态,回溯上一层,再次搜索。因此回溯算法与 DFS 的区别就是有无状态重置。 具有限界函数的深度优先生成法称为回溯法。(回溯法 = 穷举 + 剪枝)
2、基本思想
\quad \quad 回溯法简单来说就是按照深度优先的顺序,穷举所有可能性的算法,但是回溯算法比暴力穷举法更高明的地方就是回溯算法可以随时判断当前状态是否符合问题的条件。一旦不符合条件,那么就退回到上一个状态,省去了继续往下探索的时间。
\quad \quad 换句话说,回溯法可以理解为通过选择不同的岔路口寻找目的地,一个岔路口一个岔路口的去尝试找到目的地。如果走错了路,继续返回来找到岔路口的另一条路,直到找到目的地。省去了在错路上走下去的时间。
3、基本过程与求解步骤
\quad \quad 回溯法为了避免生成那些不可能产生最佳解的问题状态,要不断地利用限界函数(bounding function)来处死(剪枝)那些实际上不可能产生所需解的活结点,以减少问题的计算量。
两个常用的剪枝函数:
- 约束函数:在扩展结点处减去不满足约束的子数
- 限界函数:减去得不到最优解的子树
用回溯法解题的一般步骤:
(1)回溯出口:针对所给问题,确定问题的解空间:
(2)回溯主体:即确定结点的扩展搜索规则:就是遍历当前的状态的所有子节点,并判断下一个状态是否是满足问题条件的,如果满足问题条件,那么进入下一个状态。
(3)状态返回:以深度优先方式搜索解空间,并在搜索过程中用剪枝函数(如果当前状态不满足条件,那么返回到前一个状态。)避免无效搜索。
回溯函数万能模板
def backtrack ( 参数 ):
#回溯出口
if ( 满足题意了 ):
计数或进行其他操作
return True #有时可以省略
#回溯主体
for( 查找当前节点的周围的节点 )
进行其他的操作;
标记已经搜索过的节点
backtrack( 下一次搜索的节点 )
#状态返回
取消标记;
return False #有时可以省略
4、适用条件
即回溯法的特点(判断什么时候应该采用回溯算法)
1、问题的答案有多个元素
2、答案要满足一些约束
3、寻找答案的方式在每一个步骤中是相同的
如果一个问题是搜索求解类的问题,而且该问题的解是树状结构(不断扩张式向量),该题就可以考虑使用回溯算法。
5、经典例题
如n皇后,图的着色问题、求子集、字符串的排列等问题。
回溯算法类的题型:
- 子集、组合类问题
- 排列类问题
- 搜索、N皇后类问题、