回溯算法.docx

上传人:b****5 文档编号:2796685 上传时间:2022-11-15 格式:DOCX 页数:29 大小:39.86KB
下载 相关 举报
回溯算法.docx_第1页
第1页 / 共29页
回溯算法.docx_第2页
第2页 / 共29页
回溯算法.docx_第3页
第3页 / 共29页
回溯算法.docx_第4页
第4页 / 共29页
回溯算法.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

回溯算法.docx

《回溯算法.docx》由会员分享,可在线阅读,更多相关《回溯算法.docx(29页珍藏版)》请在冰豆网上搜索。

回溯算法.docx

回溯算法

回溯算法

寻找问题的解的一种可靠的方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到所需要的解。

理论上,当候选解数量有限并且通过检查所有或部分候选解能够得到所需解时,上述方法是可行的。

不过,在实际应用中,很少使用这种方法,因为候选解的数量通常都非常大(比如指数级,甚至是大数阶乘),即便采用最快的计算机也只能解决规模很小的问题。

对候选解进行系统检查的方法有多种,其中回溯和分枝定界法是比较常用的两种方法。

按照这两种方法对候选解进行系统检查通常会使问题的求解时间大大减少(无论对于最坏情形还是对于一般情形)。

事实上,这些方法可以使我们避免对很大的候选解集合进行检查,同时能够保证算法运行结束时可以找到所需要的解。

因此,这些方法通常能够用来求解规模很大的问题。

本章集中阐述回溯方法,这种方法被用来设计货箱装船、背包、最大完备子图、旅行商和电路板排列问题的求解算法。

4.1算法思想

回溯(backtracking)是一种系统地搜索问题解答的方法。

为了实现回溯,首先需要为问题定义一个解空间(solutionspace),这个空间必须至少包含问题的一个解(可能是最优的)。

在迷宫老鼠问题中,我们可以定义一个包含从入口到出口的所有路径的解空间;在具有n个对象的0/1背包问题中(见1.4节和2.2节),解空间的一个合理选择是2n个长度为n的0/1向量的集合,这个集合表示了将0或1分配给x的所有可能方法。

当n=3时,解空间为{(0,0,0),(0,1,0),(0,0,1),(1,0,0),(0,1,1),(1,0,1),(1,1,0),(1,1,1)}。

下一步是组织解空间以便它能被容易地搜索。

典型的组织方法是图或树。

图16-1用图的形式给出了一个3×3迷宫的解空间。

从(1,1)点到(3,3)点的每一条路径都定义了3×3迷宫解空间中的一个元素,但由于障碍的设置,有些路径是不可行的。

图16-2用树形结构给出了含三个对象的0/1背包问题的解空间。

从i层节点到i+1层节点的一条边上的数字给出了向量x中第i个分量的值xi,从根节点到叶节点的每一条路径定义了解空间中的一个元素。

从根节点A到叶节点H的路径定义了解x=[1,1,1]。

根据w和c的值,从根到叶的路径中的一些解或全部解可能是不可行的。

一旦定义了解空间的组织方法,这个空间即可按深度优先的方法从开始节点进行搜索。

在迷宫老鼠问题中,开始节点为入口节点(1,1);在0/1背包问题中,开始节点为根节点A。

开始节点既是一个活节点又是一个E-节点(expansionnode)。

从E-节点可移动到一个新节点。

如果能从当前的E-节点移动到一个新节点,那么这个新节点将变成一个活节点和新的E-节点,旧的E-节点仍是一个活节点。

如果不能移到一个新节点,当前的E-节点就“死”了(即不再是一个活节点),那么便只能返回到最近被考察的活节点(回溯),这个活节点变成了新的E-节点。

当我们已经找到了答案或者回溯尽了所有的活节点时,搜索过程结束。

例4-1[迷宫老鼠]考察图16-3a的矩阵中给出的3×3的“迷宫老鼠”问题。

我们将利用图16-1给出的解空间图来搜索迷宫。

从迷宫的入口到出口的每一条路径都与图16-1中从(1,1)到(3,3)的一条路径相对应。

然而,图16-1中有些从(1,1)到(3,3)的路径却不是迷宫中从入口到出口的路径。

搜索从点(1,1)开始,该点是目前唯一的活节点,它也是一个E-节点。

为避免再次走过这个位置,置maze(1,1)为1。

从这个位置,能移动到(1,2)或(2,1)两个位置。

对于本例,两种移动都是可行的,因为在每一个位置都有一个值0。

假定选择移动到(1,2),maze(1,2)被置为1以避免再次经过该点。

迷宫当前状态如图16-3b所示。

这时有两个活节点(1,1)(1,2)。

(1,2)成为E-节点。

在图16-1中从当前E-节点开始有3个可能的移动,其中两个是不可行的,因为迷宫在这些位置上的值为1。

唯一可行的移动是(1,3)。

移动到这个位置,并置maze(1,3)为1以避免再次经过该点,此时迷宫状态为16-3c。

图16-1中,从(1,3)出发有两个可能的移动,但没有一个是可行的。

所以E-节点(1,3)死亡,回溯到最近被检查的活节点(1,2)。

在这个位置也没有可行的移动,故这个节点也死亡了。

唯一留下的活节点是(1,1)。

这个节点再次变为E-节点,它可移动到(2,1)。

现在活节点为(1,1),(2,1)。

继续下去,能到达点(3,3)。

此时,活节点表为(1,1),(2,1),(3,1),(3,2),(3,3),这即是到达出口的路径。

程序5-13是一个在迷宫中寻找路径的回溯算法。

例4-2[0/1背包问题]考察如下背包问题:

n=3,w=[20,15,15],p=[40,25,25]且c=30。

从根节点开始搜索图16-2中的树。

根节点是当前唯一的活节点,也是E-节点,从这里能够移动到B或C点。

假设移动到B,则活节点为A和B。

B是当前E-节点。

在节点B,剩下的容量r为10,而收益cp为40。

从B点,能移动到D或E。

移到D是不可行的,因为移到D所需的容量w2为15。

到E的移动是可行的,因为在这个移动中没有占用任何容量。

E变成新的E-节点。

这时活节点为A,B,E。

在节点E,r=10,cp=40。

从E,有两种可能移动(到J和K),到J的移动是不可行的,而到K的移动是可行的。

节点K变成了新的E-节点。

因为K是一个叶子,所以得到一个可行的解。

这个解的收益为cp=40。

x的值由从根到K的路径来决定。

这个路径(A,B,E,K)也是此时的活节点序列。

既然不能进一步扩充K,K节点死亡,回溯到E,而E也不能进一步扩充,它也死亡了。

接着,回溯到B,它也死亡了,A再次变为E-节点。

它可被进一步扩充,到达节点C。

此时r=30,cp=0。

从C点能够移动到F或G。

假定移动到F。

F变为新的E-节点并且活节点为A,C,F。

在F,r=15,cp=25。

从F点,能移动到L或M。

假定移动到L。

此时r=0,cp=50。

既然L是一个叶节点,它表示了一个比目前找到的最优解(即节点K)更好的可行解,我们把这个解作为最优解。

节点L死亡,回溯到节点F。

继续下去,搜索整棵树。

在搜索期间发现的最优解即为最后的解。

例4-3[旅行商问题]在这个问题中,给出一个n顶点网络(有向或无向),要求找出一个包含所有n个顶点的具有最小耗费的环路。

任何一个包含网络中所有n个顶点的环路被称作一个旅行(tour)。

在旅行商问题中,要设法找到一条最小耗费的旅行。

图16-4给出了一个四顶点网络。

在这个网络中,一些旅行如下:

1,2,4,3,1;1,3,2,4,1和1,4,3,2,1。

旅行2,4,3,1,2;4,3,1,2,4和3,1,2,4,3和旅行1,2,4,3,1一样。

而旅行1,3,4,2,1是旅行1,2,4,3,1的“逆”。

旅行1,2,4,3,1的耗费为66;而1,3,2,4,1的耗费为25;1,4,3,2,1为59。

故1,3,2,4,1是该网络中最小耗费的旅行。

顾名思义,旅行商问题可被用来模拟现实生活中旅行商所要旅行的地区问题。

顶点表示旅行

商所要旅行的城市(包括起点)。

边的耗费给出了在两个城市旅行所需的时间(或花费)。

旅行表示当旅行商游览了所有城市再回到出发点时所走的路线。

旅行商问题还可用来模拟其他问题。

假定要在一个金属薄片或印刷电路板上钻许多孔。

孔的位置已知。

这些孔由一个机器钻头来钻,它从起始位置开始,移动到每一个钻孔位置钻孔,然后回到起始位置。

总共花的时间是钻所有孔的时间与钻头移动的时间。

钻所有孔所需的时间独立于钻孔顺序。

然而,钻头移动时间是钻头移动距离的函数。

因此,希望找到最短的移动路径。

另有一个例子,考察一个批量生产的环境,其中有一个特殊的机器可用来生产n个不同的产品。

利用一个生产循环不断地生产这些产品。

在一个循环中,所有n个产品被顺序生产出来,然后再开始下一个循环。

在下一个循环中,又采用了同样的生产顺序。

例如,如果这台机器被用来顺序为小汽车喷红、白、蓝漆,那么在为蓝色小汽车喷漆之后,我们又开始了新一轮循环,为红色小汽车喷漆,然后是白色小汽车、蓝色小汽车、红色小汽车,..,如此下去。

一个循环的花费包括生产一个循环中的产品所需的花费以及循环中从一个产品转变到另一个产品的花费。

虽然生产产品的花费独立于产品生产顺序,但循环中从生产一个产品转变到生产另一个产品的花费却与顺序有关。

为了使耗费最小化,可以定义一个有向图,图中的顶点表示产品,边<(i,j)>上的耗费值为生产过程中从产品i转变到产品j所需的耗费。

一个最小耗费的旅行定义了一个最小耗费的生产循环。

既然旅行是包含所有顶点的一个循环,故可以把任意一个点作为起点(因此也是终点)。

针对图16-4,任意选取点1作为起点和终点,则每一个旅行可用顶点序列1,v2,.,vn,1来描述,

v2,.,vn是(2,3,.,n)的一个排列。

可能的旅行可用一个树来描述,其中每一个从根到叶的路

径定义了一个旅行。

图16-5给出了一棵表示四顶点网络的树。

从根到叶的路径中各边的标号定义了一个旅行(还要附加1作为终点)。

例如,到节点L的路径表示了旅行1,2,3,4,1,而到节点O的路径表示了旅行1,3,4,2,1。

网络中的每一个旅行都由树中的一条从根到叶的确定路径来表示。

因此,树中叶的数目为(n-1)!

回溯算法将用深度优先方式从根节点开始,通过搜索解空间树发现一个最小耗费的旅行。

对图16-4的网络,利用图16-5的解空间树,一个可能的搜索为ABCFL。

在L点,旅行1,2,3,4,1作为当前最好的旅行被记录下来。

它的耗费是59。

从L点回溯到活节点F。

由于F没有未被检查的孩子,所以它成为死节点,回溯到C点。

C变为E-节点,向前移动到G,然后是M。

这样构造出了旅行1,2,4,3,1,它的耗费是66。

既然它不比当前的最佳旅行好,抛弃它并回溯到G,然后是C,B。

从B点,搜索向前移动到D,然后是H,N。

这个旅行1,3,2,4,1的耗费是25,比当前的最佳旅行好,把它作为当前的最好旅行。

从N点,搜索回溯到H,然后是D。

在D点,再次向前移动,到达O点。

如此继续下去,可搜索完整个树,得出1,3,2,4,1是最少耗费的旅行。

当要求解的问题需要根据n个元素的一个子集来优化某些函数时,解空间树被称作子集树(subsettree)。

所以对有n个对象的0/1背包问题来说,它的解空间树就是一个子集树。

这样一棵树有2n个叶节点,全部节点有2n+1-1个。

因此,每一个对树中所有节点进行遍历的算法都必须耗时(2n)。

当要求解的问题需要根据一个n元素的排列来优化某些函数时,解空间树被称作排列树(permutat

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1