数据结构第十章(2)

上传人:子 文档编号:51937264 上传时间:2018-08-17 格式:PPT 页数:33 大小:186KB
返回 下载 相关 举报
数据结构第十章(2)_第1页
第1页 / 共33页
数据结构第十章(2)_第2页
第2页 / 共33页
数据结构第十章(2)_第3页
第3页 / 共33页
数据结构第十章(2)_第4页
第4页 / 共33页
数据结构第十章(2)_第5页
第5页 / 共33页
点击查看更多>>
资源描述

《数据结构第十章(2)》由会员分享,可在线阅读,更多相关《数据结构第十章(2)(33页珍藏版)》请在金锄头文库上搜索。

1、 10.3 回溯法有许多问题,当需要找出它的解集或者要求回答什么解是 满足某些约束条件的最佳解时,往往要使用回溯法。回溯法的基本做法是搜索,或是一种组织得井井有条的 、能避免不必要搜索的穷举式搜索法。这种方法适用于解一 些组合数相当大的问题。回溯法在问题的解空间树中,按深度优先策略,从根结 点出发搜索解空间树。算法搜索至解空间树的任意一点时, 先判断该结点是否包含问题的解:如果肯定不包含,则跳过 对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则 ,进入该子树,继续按深度优先策略搜索。 一、回溯法的算法框架1.问题的解空间:应用回溯法解问题时,首先应明确定义问题 的解空间。问题的解空间应至少

2、包含问题的一个(最优)解。例如:01背包问题:给定n种物品和一个背包,物品i的重量 是wi,其价值为vi,背包的最大负重量是C:如何选择装入背包 的物品,可以使得背包中物品的总价值最大?对于有n种可选物品的0-1背包问题,其解空间由长度为n的0 -1向量组成。当n3时,解空间为:000、001、010、011、100 、101、110、111;为了能够方便的使用回溯法解决问题,我们 一般将解空间组织成树或图的形式; 2生成解空间的方法(1)扩展结点:一个正在产生儿子的结点称为扩展结点;(2)活结点:一个自身已生成但其儿子还没有全部生成的节点称做活结点;(3)死结点:一个所有儿子已经产生的结点称

3、做死结点;深度优先的问题状态生成法:如果对一个扩展结点R,一 旦产生了它的一个儿子C,就把C当做新的扩展结点。在完成 对子树C(以C为根的子树)的穷尽搜索之后,将R重新变成 扩展结点,继续生成R的下一个儿子(如果存在).回溯法:为了避免生成那些不可能产生最佳解的问题状 态,要不断地利用限界函数(bounding function)来处死那 些实际上不可能产生所需解的活结点,以减少问题的计算量 。具有限界函数的深度优先生成法称为回溯法。 3避免无效搜索的方法:例1:对于n3的01背包问题,考虑:重量W(16, 15,15);价值p(45,25,25);背包承重C30; 开始搜索解空间;最优解X=

4、(0,1,1),最优值V=50例2:旅行售货员问题:某售货员要到若干个城市去推销商品,已 知各城市之间的路程(或旅费)。他要选定一条从驻地出发,经 过每个城市一次,最后回到驻地的路线,使总的路程(或旅费) 最短;4123206305410回溯法搜索解空间树时,通常采用两种策略避免无效搜索 ,提高搜索效率:(1)用约束函数在扩展结点处剪去不满足约束的子树;(2)用限界函数剪去得不到最优解的子树。这两类函数通称为剪枝函数;最优解(1,3,2,4,1),最优值 25 44子集树与排列树:(1)子集树:当所给的问题从n个元素的集合S中找出S满足某 种性质的子集时,相应的解空间称为子集树;(n个元素,有

5、2n 个叶子结点,满二叉树;01背包问题)用回溯法搜索子集树的一般算法:void backtrack (int t) if (tn) output(x);elsefor (int i=0;in) output(x);elsefor (int i=t;i#define MaxSize 100 /最多物品数int limitw; /限制的总重量int maxwv=0; /存放最优解的总价值int maxw;int n; /实际物品数int optionMaxSize; / 存放最终解int opMaxSize; /存放临时解struct int weight;int value;AMaxSize;

6、 /存放物品数组void Knap( int i, int tw, int tv) /考虑第i个物品int j;if (i=n) /找到一个叶子结点if (twmaxv) /找到一个满足条件地更优解,保存它maxv=tv; maxw=tw;for(j=0;j0) /对所有列执行以下语句;qk=qk+1; /移到下一行While( qk=fj) ai=true; j=i; count+; else ai=false; return count; 由于输入的活动以其完成时间的非减序排列,所 以算法greedySelector每次总是选择具有最早完成时 间的相容活动加入集合A中。直观上,按这种方法选

7、 择相容活动为未安排活动留下尽可能多的时间。也就 是说,该算法的贪心选择的意义是使剩余的可安排时 间段极大化,以便安排尽可能多的相容活动。算法greedySelector的效率极高。当输入的活动 已按结束时间的非减序排列,算法只需O(n)的时间安 排n个活动,使最多的活动能相容地使用公共资源。 如果所给出的活动未按非减序排列,可以用O(nlogn) 的时间重排。 例:设待安排的11个活动的开始时间和结束时间按结束时间的 非减序排列如下:若被检查的活动i的开始时间Si小于最近选择的活动 j的结束时间fi,则不选择活动i,否则选择活动i加入 集合A中。 贪心算法并不总能求得问题的整体最优解。但对

8、于活动安排问题,贪心算法greedySelector却总能求得 的整体最优解,即它最终所确定的相容活动集合A的规 模最大。这个结论可以用数学归纳法证明。i1234567891011Si 130535688212Fi 4567891011121314三、贪心算法的基本要素对于一个具体的问题,怎么知道是否可用贪心算法解此问 题,以及能否得到问题的最优解呢?这个问题很难给予肯定的 回答。但是,从许多可以用贪心算法求解的问题中看到这类问题 一般具有2个重要的性质:贪心选择性质和最优子结构性质。 1.贪心选择性质所谓贪心选择性质是指所求问题的整体最优解可以通过一 系列局部最优的选择,即贪心选择来达到。这

9、是贪心算法可行 的第一个基本要素,也是贪心算法与动态规划算法的主要区别 。动态规划算法通常以自底向上的方式解各子问题,而贪心 算法则通常以自顶向下的方式进行,以迭代的方式作出相继的 贪心选择,每作一次贪心选择就将所求问题简化为规模更小的 子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必 须证明每一步所作的贪心选择最终导致问题的整体最优解。2.最优子结构性质当一个问题的最优解包含其子问题的最优解时, 称此问题具有最优子结构性质。问题的最优子结构性 质是该问题可用动态规划算法或贪心算法求解的关键 特征。3.贪心算法与动态规划算法的差异贪心算法和动态规划算法都要求问题具有最优子 结构性质,

10、这是2类算法的一个共同点。但是,对于具 有最优子结构的问题应该选用贪心算法还是动态规划 算法求解?是否能用动态规划算法求解的问题也能用贪 心算法求解?下面研究2个经典的组合优化问题,并以 此说明贪心算法与动态规划算法的主要差别。 (1)0-1背包问题:给定n种物品和一个背包。物品i的重量是Wi,其 价值为Vi,背包的容量为C。应如何选择装入背包的 物品,使得装入背包中物品的总价值最大?在选择装入背包的物品时,对每种物品i只有2种 选择,即装入背包或不装入背包。不能将物品i装入 背包多次,也不能只装入部分的物品i。(2)背包问题: 与0-1背包问题类似,所不同的是在选择物品i装 入背包时,可以选

11、择物品i的一部分,而不一定要全 部装入背包,1in。这2类问题都具有最优子结构性质,极为相似, 但背包问题可以用贪心算法求解,而0-1背包问题却 不能用贪心算法求解。(3)用贪心算法解背包问题的基本步骤:首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择 策略,将尽可能多的单位重量价值最高的物品装入背包。若将这 种物品全部装入背包后,背包内的物品总重量未超过C,则选择单 位重量价值次高的物品并尽可能多地装入背包。依此策略一直地 进行下去,直到背包装满为止。 具体算法可描述如下: float knapsack(float *p,float *w,float *x,float m,int

12、n) /p存放物品价格;w存放重量;物品已经按pi/wi降序 存放;m为背包内物品总重;n为物品件数; x存放解向量; int i; float s=0;for (i=0;i0) xi=m/wi; s+=pi*xi; i+; return s; 算法knapsack的时间代价为O(n),但该方法的主 要计算时间在于将各种物品依其单位重量的价值从大到小 排序。因此,此方法的计算时间上界为O(nlogn)。当然 ,为了证明算法的正确性,还必须证明背包问题具有贪心 选择性质。 对于0-1背包问题,贪心选择之所以不能得到 最优解是因为在这种情况下,它无法保证最终能将 背包装满,部分闲置的背包空间使每公

13、斤背包空间 的价值降低了。事实上,在考虑0-1背包问题时, 应比较选择该物品和不选择该物品所导致的最终方 案,然后再作出最好选择。由此就导出许多互相重 叠的子问题。这正是该问题可用动态规划算法求解 的另一重要特征。实际上也是如此,动态规划算法 的确可以有效地解0-1背包问题。 四、最优装载问题:有一批集装箱要装上一艘载重量为c的轮船。其中集装箱i 的重量为Wi。最优装载问题要求确定在装载体积不受限制的情 况下,将尽可能多的集装箱装上轮船。 1.算法描述最优装载问题可用贪心算法求解。采用重量最轻者先装的 贪心选择策略,可产生最优装载问题的最优解 float loading(float c, fl

14、oat w , int x ) int n; for (int i = 0; i n; i+) di = new Element(wi,i); MergeSort.mergeSort(d); float opt=0; for (int i = 0; i n; i+) xi = 0; for (int i = 0; i n i+) xdi.i = 1; opt+=di.w; c -= di.w; return opt; 2.贪心选择性质可以证明最优装载问题具有贪心选择性质。 3.最优子结构性质最优装载问题具有最优子结构性质。由最优装载问题的贪心选择性质和最优子结构性 质,容易证明算法loading的正确性。算法loading的 主要计算量在于将集装箱依其重量从小到大排序,故 算法所需的计算时间为 O(nlogn)。五、最小生成树问题:设G =(V,E)是无向连通带权图,即一个网络。E中每条边 (v,w)的权为cvw。如果G的子图G是一棵包含G的所有顶 点的树,则称G为G的生成树。生成树上各边权的总和称为 该生成树的耗费。在G的所有生成树中,耗费最小的生成树称 为G的最小生成树。 1.最小生成树性质用贪心算法设计策略可以设计出构造最小生成树的有效 算法。本节介绍的构造最小生成树的

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号