来源http://www.xzbu.com/8/view-5870114.htm
1.1回溯法
回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。这种以深度优先方式系统搜索问题解的算法称为回溯法。
1.2分支限界法
分支限界法是以广度优先或以最小耗费优先的方式搜索解空间树,在每一个活结点处,计算一个函数值,并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解,这种方法称为分支限界法。
2、回溯法的基本思想
用回溯法解问题时,应明确定义问题的解空间。问题的解空间至少应包含问题的一个解。之后还应将解空间很好的组织起来,使得能用回溯法方便的搜索整个解空间。在组织解空间时常用到两种典型的解空间树,即子集树和排列树。确定了解空间的组织结构后,回溯法从开始结点出发,以深度优先方式搜索整个解空间。这个开始结点成为活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。此时,应往回移动至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法以这种工作方式递归的在解空间中搜索,直至找到所要求的解或解空间中已无活结点时为止。
3、分支限界法的基本思想
用分支限界法解问题时,同样也应明确定义问题的解空间。之后还应将解空间很好的组织起来。分支限界法也有两种组织解空间的方法,即队列式分支限界法和优先队列式分支限界法。两者的区别在于:队列式分支限界法按照队列先进先出的原则选取下一个节点为扩展节点,而优先队列式分支限界法按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。分支限界法常以广度优先或以最小耗费优先的方式搜索问题的解空间树。在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。
4、回溯法的设计原理
在设计一个回溯算法时,通常按照以下步骤进行:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
在一般情况下用递归方法实现回溯法的基本框架如下:
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);
}
}
其中:t表示递归深度,output(x)记录或输出得到的可行解x,f(n,t)和g(n,t)分别表示在当前扩展结点处未搜索过的子树的起始编号和终止编号,h(i)表示当前扩展结点处的第i个可选值,constraint(t)和bound(t)表示当前扩展结点的约束函数和限界函数。
5、分支限界法的设计原理
在设计一个分支限界算法时,通常按照以下步骤进行:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以广度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
6、回溯法与分支限界法的差异及应用
回溯法与分支定界法都是在问题的解空间上搜索问题解的算法。但是两者是有区别的:
首先,求解目标不同:
一般而言,回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是尽快地找出满足约束条件的一个解。
其次,搜索方法不同:
由于求解目标不同,导致分支限界法与回溯法对解空间的搜索方式也不同,回溯法采用深度优先方法搜索解空间,而分支限界法一般采用用广度优先或以最小耗费优先的方式搜索解空间。
再次,对扩展结点的扩展方式不同:
在搜索解空间书中两者的主要区别在于它们对当前扩展结点所采用的扩展方式不同。在回溯法中,如果当前的扩展结点不能够再向纵深方向移动,则当前扩展结点就成为死结点,此时应回溯到最近的一个活结点处,并使此活结点成为扩展结点。而在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。
最后,存储空间的要求不同:
分支限界法的存储空间比回溯法大得多,因此当内存容量有限时,回溯法成功的可能性更大。
下面结合具体的实例来说明何种情况下比较适合采用回溯法,何种情况下比较适合采用分支限界法:
适合采用回溯法的问题:最典型的代表如n后问题,即在n*n个格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。对于n后问题,解与解之间不存在优劣的区别。必须要搜索到叶节点时才能确定出一组解。这种情况下,我们采用回溯法来解决时,采用排列树的解空间结构,在最坏的情况下,其堆栈的深度不会超过n。而采用分支限界法时,由于解之间不存在优劣关系,故不可能用限界函数剪枝,需要较大的存储空间。
适合采用分支限界法的问题:最典型的代表如布线问题,即印刷电路板将布线区域划分成n*m个方格阵列。要求确定连接方格a的中点到方格b的中点的最短布线方案。在布线时,电路只能沿直线或直角布线。为了避免线路相交,已布了线的方格做了封锁标记,其他线路不允许穿过被封锁的方格。此问题,如果采用回溯法来解决时,为了找到最短路径,必须把整个区域的所有路径逐一搜索后才能得到最优解,这使得算法效率较低。而如果用分支限界法来解决,则可以保证找到的解是最短的布线方案,因为如果存在一条由a至b的更短的路径,b结点一定会更早地被加入到活结点队列中并得到处理。