回溯算法理论基础

代码模板

1
2
3
4
5
6
7
8
9
void backtrack(int t) {
if (t > n) output(x);
else {
for (int i = f(n, t); i <= g(n, t); i++) {
x[t] = h(i);//当前解
if (constraint(t) && bound(t)) backtrack(t + 1);
}
}
}

回溯法解决的问题都可以抽象为树形结构,是的,我指的是所有回溯法的问题都可以抽象为树形结构!

因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度

回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。

大家可以从图中看出for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历,这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。

卡哥模板

1
2
3
4
5
6
7
8
9
10
11
12
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}

for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}

组合问题

每一层递归就是相当于一个for循环。

嵌套多少个for循环,就相当于递归多少次