一、简介
回溯法是一种通过试错来寻找问题解的算法策略。它尝试分步解决一个问题,在每一步中,它都会做出一个选择,如果这个选择最终导致问题无解或者不是最优解,算法会撤销上一步或上几步的选择,然后尝试其他可能的选择。回溯法通常用于解决组合问题、约束满足问题和优化问题。
关键特点:
选择:在每个决策点,算法需要在多个可能的选择中做出决定。
约束:问题通常有一系列的约束条件,这些约束决定了哪些选择是合法的。
目标:算法试图找到满足所有约束的解,或者在有限的步骤内找到最优解。
回溯:当当前选择导致无法满足约束或者无法达到目标时,算法会回溯到上一个决策点,尝试其他选择。
二、解题步骤
- 初始化:从问题的初始状态开始。 选择:在当前状态,根据约束条件选择一个可能的行动。
- 约束检查:检查当前的选择是否满足所有约束。如果不满足,回溯到上一步。
- 目标检查:如果当前的选择满足了所有约束,检查是否达到了目标状态。如果是,记录解并继续搜索其他可能的解;如果不是,继续下一步。
- 回溯:如果当前路径无法达到目标状态,回溯到上一个决策点,尝试其他选择。
- 终止条件:当所有可能的选择都已尝试,或者找到了所有可能的解,算法终止。
回溯三部曲
确定递归函数的返回值以及参数 -回溯函数终止条件-回溯搜索的遍历过程
三、应用场景
- 八皇后问题
在8x8的棋盘上放置八个皇后,使得它们互不攻击(即任何两个皇后都不在同一行、同一列或同一对角线上)。 - 图的着色问题
给定一个图,用最少的颜色给图的顶点着色,使得相邻的顶点颜色不同。 - 旅行商问题(TSP)
找到一条经过所有城市且总旅行距离最短的路径。 - 子集和问题
从给定的一组数中找到所有子集,使得它们的和为特定的目标值。 - 排列和组合问题
生成所有可能的排列或组合。 - 密码破解
尝试所有可能的密码组合,直到找到正确的密码。
四、模板函数
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}