理论基础
回溯是一种搜索方式,通常通过穷举来解决问题,核心思想是从一个初始状态出发、暴力搜索所有可能的方案,遇到正确的解法则记录下来,直到结束,这是一个典型的深度优先搜索思想:不撞南墙不回头
回溯:时间回溯!
画出决策树
这一步是为了后面更好的进行深度搜索,以排列问题为例,可以遍历可选的所有情况,然后一个个画下去,我们的做法就是用代码遍历这棵树,**检查叶子节点的子问题是否为解,**在这个过程中维护一个解集和一个遍历集
剪枝
对于这个决策树,我们要把不需要遍历的树枝剪掉,加快速度
模板
void backtrack(State *state, vector<Choice *> &choices, vector<State *> &res) {// 判断是否为解if (isSolution(state)) {// 记录解recordSolution(state, res);// 不再继续搜索return;}// 遍历所有选择for (Choice choice : choices) {// 剪枝:判断选择是否合法if (isValid(state, choice)) {// 尝试:做出选择,更新状态makeChoice(state, choice);backtrack(state, choices, res);// 回退:撤销选择,恢复到之前的状态undoChoice(state, choice);}}
}
组合
vector<int> temp;
void dfs(int cur, int n) {if (cur == n + 1) {// 记录答案// ...return;}// 考虑选择当前位置temp.push_back(cur);dfs(cur + 1, n, k);temp.pop_back();// 考虑不选择当前位置dfs(cur + 1, n, k);
}