预览加载中,请您耐心等待几秒...
1/10
2/10
3/10
4/10
5/10
6/10
7/10
8/10
9/10
10/10

亲,该文档总共20页,到这已经超出免费预览范围,如果喜欢就直接下载吧~

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

1、回溯法(1)描述:回溯法是一种选优搜索法,按选优条件向前搜索,以达成目的。但当探索到某一步时,发现原先选择并不优或达不到目的,就退回一步重新选择,这种走不通就退回再走的技术为回溯法。(2)原理:回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。假如肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。这种方法合用于解一些组合数相称大的问题。有许多问题,当需要找出它的解集或者规定回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。(3)问题的解空间问题的解向量:回溯法希望一个问题的解可以表达成一个n元式(x1,x2,…,xn)的形式。显约束:对分量xi的取值限定。隐约束:为满足问题的解而对不同分量之间施加的约束。解空间:对于问题的一个实例,解向量满足显式约束条件的所有多元组,构成了该实例的一个解空间。注意:同一个问题可以有多种表达,有些表达方法更简朴,所需表达的状态空间更小(存储量少,搜索方法简朴)。例1:n=3的0——1背包问题的回溯法搜索过程。W=[16,15,15]p=[45,25,25]C=30例2:旅行售货员问题。某售货员要到若干城市去推销商品,已知各城市之间的路程(旅费),他要选定一条从驻地出发,通过每个城市一遍,最后回到驻地的路线,使总的路程(总旅费)最小。(4)生成问题状态的基本方法扩展结点:一个正在产生儿子的结点称为扩展结点。活结点:一个自身已生成但其儿子还没有所有生成的节点称做活结点。死结点:一个所有儿子已经产生的结点称做死结点。深度优先的问题状态生成法:假如对一个扩展结点R,一旦产生了它的一个儿子C,就把C当做新的扩展结点。在完毕对子树C(以C为根的子树)的穷尽搜索之后,将R重新变成扩展结点,继续生成R的下一个儿子(假如存在)。宽度优先的问题状态生成法:在一个扩展结点变成死结点之前,它一直是扩展结点。回溯法:为了避免生成那些不也许产生最佳解的问题状态,要不断地运用限界函数(boundingfunction)来处死那些事实上不也许产生所需解的活结点,以减少问题的计算量。具有限界函数的深度优先生成法称为回溯法。(5)回溯法的基本思想基本思想:用回溯法解题的一个显著特性是在搜索过程中动态产生问题的解空间。在任何时刻,算法只保存从根结点到当前扩展结点的途径。假如解空间树中从根结点到叶结点的最长途径的长度为h(n),则回溯法所需的计算空间通常为O(h(n))。而显式地存储整个解空间则需要O(2h(n))或O(h(n)!)内存空间。解题环节:1)针对所给问题,定义问题的解空间;2)拟定易于搜索的解空间结构;3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。常用剪枝函数:用约束函数在扩展结点处剪去不满足约束的子树;用限界函数剪去得不到最优解的子树。递归回溯:回溯法对解空间作深度优先搜索,因此,在一般情况下用递归方法实现回溯法。[cpp]viewplaincopyvoidbacktrack(intt){if(t>n)output(x);//已到叶子结点,输出结果elsefor(inti=f(n,t);i<=g(n,t);i++){x[t]=h(i);if(constraint(t)&&bound(t))backtrack(t+1);}}f(n,t),g(n,t):表达当前扩展结点处未搜索过的子树的起始编号和终止编号。h(i):表达在当前扩展结点处x[t]的第i个可选值。迭代回溯:采用树的非递归深度优先遍历算法,可将回溯法表达为一个非递归迭代过程。[cpp]viewplaincopyvoiditerativeBacktrack(){intt=1;while(t>0){if(f(n,t)<=g(n,t))for(inti=f(n,t);i<=g(n,t);i++){x[t]=h(i);if(constraint(t)&&bound(t)){if(solution(t))output(x);elset++;}}elset--;}}子集树与排列树:子集树:当所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间称为子集树。例如,那个物品的0-1背包问题所相应的解空间树就是一颗子集树。这类子集问题通常有2^n个叶节点,其节点总个数为2^(n+1)-1。遍历子集树的任何算法均需要O(2^n)的计算时间。用回溯法遍历子集树的一般算法可描述如下:[cpp]viewplaincopyvoidbacktrack(intt){if(t>n)output(x);elsefor(inti=0;