资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,回溯法解决,01,背包问题,回溯法解决,01,背包问题,1,、算法思想,2,、问题描述,3,、设计实现,回溯法解决,01,背包问题,回溯法:是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其原先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。,课堂上老师已经讲解过用回溯法解决,n-,皇后问题,,m-,图着色问题以及哈密顿环问题,他们有相同的特征即问题的求解目标都是求满足约束条件的全部可行解。而,0/1,背包是最优化问题,还需要使用限界函数剪去已能确认不含最优答案结点的子树。,回溯法解决,0/1,背包问题,运用回溯法解题通常包含以下三个步骤:,a.,针对所给问题,定义问题的解空间;,b.,确定易于搜索的解空间结构;,c.,以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索;,0/1,背包问题概述,在,0/1,背包问题中,需对容量为,c,的背包进行装载。从,n,个物品中选取装入背包的物品,每件物品,i,的重量为,w,i,价值为,p,i,。,对于可行的背包装载,背包中的物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高,即 取得最大值。约束条件为,c,和 。,在这个表达式中,需求出,x,i,的值。,x,i,=1,表示物品,i,装入背包中,,x,i,=0,表示物品,i,不装入背包。,回溯法解决,01,背包问题,回溯法解决,01,背包问题,问题举例最优值上界,对于,0-1,背包问题回溯法的一个实例,,n=4,,,M=7,,,p=9,10,7,4,w=3,5,2,1.,这,4,个物品的单位重量价值分别为,3,2,3,5,4.,以物品为单位价值的递减序装入物品。先装入物品,4,,然后装入物品,3,和,1.,装入这,3,个物品后,剩余的背包容量为,1,,只能装入,0.2,个物品,2.,由此可得到一个解为,x=1,0.2,1,1,其相应的价值为,22.,尽管这不是一个可行解,但可以证明其价值是最有大的上界。因此,对于这个实例,最优值不超过,22.,回溯法解决,01,背包问题,01,背包问题是一个子集选取问题,适合于用子集树表示,01,背包问题的解空间。在搜索解空间树是,只要其左儿子节点是一个可行结点,搜索就进入左子树,在右子树中有可能包含最优解是才进入右子树搜索。否则将右子树剪去。,问题分析:,首先是将可供选择的物品的个数输入程序,将物品排成一列,计算总物品的体积,s,,然后输入背包的实际体积,V,,如果背包的体积小于,0,或者大于物品的总体积,s,,则判断输入的背包体积错误,否则开始顺序选取物品装入背包,假设已选取了前,i,件物品之后背包还没有装满,则继续选取第,i+1,件物品,若该件物品,太大,不能装入,则弃之而继续选取下一件,直至背包装满为止。但如果在剩余的物品中找不到合适的物品以填满背包,则说明,刚刚,装入背包的那件物品,不合适,,应将它取出,弃之一边,,继续再从,它之后,的物品中选取,如此重复,直至求得满足条件的解。,因为回溯求解的规则是,后进先出,,所以要用到栈来存储符合条件的解,在存储过程中,利用数组来存储各个物品的体积,然后用深度优先的搜索方式求解,将符合条件的数组元素的下标存入栈里,最后得到符合条件的解并且实现输出。,限界函数,设,r,是当前剩余物品价值总和;,cp,是当前结点,X,的价值;,bp,是当前,X,结点上界函数值。,L,始终为已搜索到的答案节点中受益的最大值,当,cp+r=bpL,时可剪去以,X,为根的子树。,计算右子树中解的上界的更好方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。由此得到的价值是右子树中解的上界。,L,始终为已搜索到的答案节点中受益的最大值,最优解必定大于等于,L,,对于任意结点,X,,若其上界函数值,bpn),Print();,if(bestPricebp),bp=bestPrice;,for(int j=1;j=n;j+),bAj=bestAnswerj;,return;,回溯法解决,01,背包问题,if(currentWeight+weighti=c), /,将物品,i,放入背包,搜索左子树,bestAnsweri = 1;,currentWeight += weighti;,bestPrice += pricei;,Backtracking(i+1); /,完成上面的递归,返回到上一结点,物品,i,不放入背包,准备递归右子树,currentWeight -= weighti;,bestPrice -= pricei;, bestAnsweri = 0;,Backtracking(i+1);,回溯法解决,01,背包问题,void Print(), int i;,printf(n,路径为,);,for(i=1;in;+i),printf(%d,bestAnsweri);,printf(%dt,价值为,%dn,bestAnsweri,bestPrice);,void main(), int i;,/*,输入部分*,/,printf(,请输入物品的数量,:n);,scanf(%d,printf(,请输入背包的容量,(,能承受的重量,):n);,scanf(%d,printf(,请依次输入,%d,个物品的重量,:n,n);,回溯法解决,01,背包问题,for(i=1;i=n;i+),scanf(%d,printf(,请依次输入,%d,个物品的价值,:n,n);,for(i=1;i=n;i+),scanf(%d,printf(,各符合条件的路径为:,n);,Backtracking(1);,printf(*n);,printf(nthe best answer is );,for(i=1;in;+i),printf(%d,bAi);,printf(%dtthe price is %dn,bAi,bp);,printf(nn,总共搜索结点数,%dn,times);,回溯法解决,01,背包问题,
展开阅读全文