今天来讲回溯算法!!
1.回溯算法的基础理论:
回溯法是一种组织搜索的一般技术,有“通用的解题法”之称,
用它可以系统地搜索一个问题的所有解或任意解。有许多问题,
当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,
往往要使用回溯法。可以系统地搜索一个问题的所有解或任意解,
既有系统性又有跳跃性。回溯法的基本做法是搜索,
或是一种组织的井井有条,
能避免不必要搜索的穷举式搜索法。
这种以深度优先的方式系统地搜索问题的解的方法称为回溯法
1.1问题的解空间应用回溯法求解时,需要明确定义问题的解空间。问题的解空间应至少包含问题的一个(最解)
定义了问题的解空间后,还应将解空间很好地组织起来,使得回溯法能更方便地搜索解空间,通常组织成树或图的形式。
1.2回溯法的基本思想
在确定了解空间的组织结构后,回溯从开始节点(根节点)出发,以深度优先的方式搜索整个解空间。这个开始节点成为一个活结点,同时成为当前的扩展结点。在当前的扩展结点,搜索向深度方向进入一个新的节点。这个新节点成为一个新的活结点,并成为当前的扩展结点。若在当前扩展结点处不能再向深度方向移动,则当前的扩展结点成为死节点,即该活结点成为死节点。此时回溯到最近的一个活结点处,并使得这个活结点成为当前的扩展结点。回溯法以这样的方式递归搜索整个解空间(树),直到满足终止条件。
1. 使用回溯法解题包含三个步骤:
2. (1)针对所给问题,定义问题的空间树
3. (2)确定易于搜素的解空间结构
4. (3)以深度优先的方式搜索解空间树,并且在搜索过程中用剪枝函数避免无效搜索
1.3子集树与排列树
有时问题是要从一个集合中的所有子集中搜索一个集合,作为问题的解。或者从一个集合的排列中搜索一个排列,作为问题的解。回溯算法可以很方便地遍历一个集合的所有子集或者所有排列。当问题是要计算n个问题的子集,以便达到某个优化目标时,可以把这个解空间组织成一个子集树。例如,n个物品的0-1背包问题相应的解空间树就是一个子集树。这类子集树通常有2的n次方个叶节点
回溯算法搜索子集树的伪代码
void Backtrack(int t) { //t 表示当前是树的第t层,即对集合 S 中的第 t 个元素进行判断
if (t > n)
output(x); //大于S中总的元素个数 ,遍历完成
else // 两种可能 加入或者不加入到解集合 每个节点只有两个子树
x[t] = i; //即0 - 1
if (Constraint(t) && Bound(t)){ //满足约数条件
Backtrack(t + 1); //对 t+1 层进行判断
}
}
}
回溯算法搜索排列树的伪代码
void Backtrack(int t) { //t 表示集合 S 的第 t 个元素
if (t > n)
output(x);
else
for (int i = t; i <= n; i++) { //第t 个元素与其后面的所有元素进行交换位置
//为了保证排列中每个元素不同,通过交换x[t], x[i]来实现
swap(x[t], x[i]);
int(t) && bound(t)){
backtrack(t + 1);
}
swap(x[t], x[i]); //恢复状态
}
}
基本应用载问题,背包问题,m色问题,后问题,流作业问题,子问题。
绑定之后会不会在手机上收到有关acwing的消息?
不会
ok
你绑定手机了吗
yes
早就绑定了
是回溯不是回渊!
打错
大佬学过回溯吗?大佬带带我!
学过
额,你才是大佬
大佬!万万不可如此!
nooooo~,你才是~~~
其实也就是昨天刚学完
哈哈哈上个学期学的
(过来找死)