0_1背包问题的多种解法_第1页
0_1背包问题的多种解法_第2页
0_1背包问题的多种解法_第3页
0_1背包问题的多种解法_第4页
0_1背包问题的多种解法_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.一、 问题描述0/1 背包问题 :现有 n 种物品,对1=i c (n1,w ) ,说明第 n 个物品被装入了背包中,前 n-1 个物品被装入容量为wwn 的背包中;否则,第n 个物品没有装入背包中,前 n-1 个物品被装入容量为w 的背包中。依此类推,直到确定第一个物品是否被装入背包为止。由此,我们可以得到如下的函数:xi0c(i, j )c(i 1, j ).1, jjwi c(i, j ) c(i 1, j )根据动态规划函数,用一个( n 1)(w 1) 的二维数组 c 存放中间变量,c i j 表示把前 i 个物品装入容量为 j 的背包中获得的最大价值。设物品的重量存放在数组wn

2、中,价值存放在数组vn 中,背包的容量为w ,数组cn 1w 1 存放迭代的结果,数组xn 存放装入背包的物品,动态规划解0-1 背包问题的源代码在文件夹动态规划法中。回溯法分析:用回溯法解0_1 背包问题时, 会用到状态空间树。在搜索状态空间树时,只要其左儿子.结点是一个可行结点,搜索就进入其左子树。当右子树有可能包含最优解时才进入右子树搜索,否则将右子树剪去。设r 是当前剩余物品价值总和; cp 是当前价值; bestp 是当前最优价值。当 cp+r bestp时,可剪去右子树。计算右子树中解的上界可以用的方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的

3、一部分而装满背包。由此得到的价值是右子树中解的上界,用此值来剪枝。为了便于计算上界,可先将物品依其单位重量价值从大到小排序,此后只要顺序考察各物品即可。在实现时,由maxboundary函数计算当前结点处的上界。它是类knap 的私有成员。 knap 的其他成员记录了解空间树种的节点信息,以减少函数参数的传递以及递归调用时所需要的栈空间。在解空间树的当前扩展结点处,仅当要进入右子树时才计算上界函数 maxboundary,以判断是否可以将右子树减去。进入左子树时不需要计算上界,因为其上界与父结点的上界相同。在调用函数 knapsack之前,需要先将各物品依其单位重量价值从达到小排序。为此目的,

4、我们定义了类 objiect。其中,运算符与通常的定义相反,其目的是为了方便调用已有的排序算法。在通常情况下,排序算法将待排序元素从小到大排序。在搜索状态空间树时,由函数 backtrack 控制。在函数中是利用递归调用的方法实现了空间树的搜索。具体的代码见回溯法文件夹。限界分支法:在解 0-1 背包问题的优先队列式界限分支法中,活结点优先队列中结点元素n 的优先级由该结点的上界函数maxboundary计算出的值 uprofit 给出。该上界函数在0-1 背包问题的回溯法总已经说明过了。 子集树中以结点 n 为根的子树中任一个结点的价值不超过n.profit 。因此我们用一个最大堆来实现活结

5、点优先队列。堆中元素类型为heapnode,其私有成员有 uprofit,profit,weight,level,和 ptr 。对于任意一个活结点n ,n.weight 是.活结点 n 所相应的重量;n.profit是 n 所相应的价值;n.uprofit是结点 n 的价值上界,最大堆以这个值作为优先级。子集空间树中结点类型为bbnode。在分支限界法中用到的类knap 与 0-1 背包问题的回溯法中用到的类knap很相似。他们的区别是新的类中没有了成员变量bestp ,而增加了新的成员bestx 。bestxi=1,当且仅当最优解含有物品i。在类 knap 中有四个函数:( 1 ) 上界函数

6、 maxboundary(), 计算节点所对应价值的上界;( 2 ) 函数 addlivenode() 是将一个新的活结点插入到子集树和优先队列中;( 3 ) 函数 maxknapsack() 实施对子集树的优先队列式分支界限搜索。其中假定物品依其单位价值从大到小已经排好序。 相应的排序过程会在算法的预处理部分完成。算法中 e 是当前扩展结点; cw 是该结点的重量; cp 是该结点的价值; up 是价值上界。算法的 while 循环不断扩展结点,直到子集树的一个叶结点成为扩展结点为止。 此时优先队列中所有活结点的价值上界均不超过该叶结点的价值。因此该叶结点相应的解为问题的最优解。在 whil

7、e 循环内部,算法首先检查当前扩展结点的左儿子结点的可行性。如果该左儿子结点是可行结点,则将它加入到子集树和活结点优先队列中。当前扩展结点的右儿子结点一定是可行结点, 仅当右儿子结点满足上界约束时才将它加入子集树和活结点优先队列。( 4 ) 函数 knapsack() 完成对输入数据的处理。其主要任务是将各物品依其单位重量价值从达到小排好序。然后调用函数maxknapsack()完成对子集树的优先队列式分支限界搜索。具体的实现代码在文件夹分支限界法中。.三、 时空效率分析穷举法:对于一个有n 个元素的集合,其子集数量为2n ,所以,不论生成子集的算法效率有多高,穷举法都会导致一个o (2n )

8、 的算法。递归法:在递归法的算法体中有一个if 判断中出现了两次递归调用比较大小所以它们之间的递归关系式可以大体表示为:t (n)2t (n1)c ,其中 t (n) 表示递归法的时间复杂度,c 是常数。求解递归方程可以知道t (n) 的量级为 o( 2n ) 。所以递归法解0-1 背包问题的时间复杂度为o( 2n ) 。递归法是耗费空间最多的算法,每次递归调用都需要压栈,导致栈的使用很频繁。动态规划法:由于函数knapsack中有一个两重for循环,所以时间复杂度为o(n+1)x(m+1).空间复复杂度也是o(n+1)x(m+1),即 o ( nm ) .回溯法:由于计算上界的函数maxbo

9、undary需要 o(n) 时间,在最坏情况下有o(2n ) 个右儿子结点需要计算上界,所以解0-1 背包问题的回溯法算法backtrack所需要的计算时间为 o( n2n ) .限界分支法:在使用限界分治法时,就是使用更好的限界剪枝函数使得不必要的解被剔除,但是在最坏情况下的解仍然是和回溯法是相同的。本算法中也是用到了计算上界的函数maxboundary需要 o(n) 的时间,而且在最坏情况下有o(2n ) 个结点需要计算上界,所以在最坏情况下的时间复杂度仍然为o(n2n ) 。.四、 运行结果递归法输出结果:.动态规划法输出结果:.回溯法输出结果:.分枝限界法输出结果:.五、 分析输出结果

10、上面测试的是每种算法在两种输入情况下得到的0-1背包问题的解。两种测试数据为:第一组:背包容量: 18 ;物品数目: 7 ;每个物品重量为:112489610 ;每个物品价值为:7881213414 。第二组:背包容量: 50 ;物品数目: 10 ;每个物品重量为:81224166935211819 ;每个物品价值为:34325667543245564670 。四种实现的算法中,只有回溯法没能够得到预期的最优解。(但是可能是算法设计时的问题,其实回溯法是穷举法的变形,肯定能够得到最优解的,这里是我设计函数的问题。从递归法的输出可知, 它的结果就是我们想要的最优解)。从时间复杂度和空间复杂度分析

11、可知,动态规划法的时间复杂度是最小的,但是同时它的空间复杂度又是最大的。这里就可以看出在设计算法的过程中要考虑它们的平衡问题。在时间要求比较快的情况下,我们就可以选择动态规划法; 在空间要求比较高时,我们就可以使用穷举法或是分枝限界法等其他改进的穷举法。各种算法在解背包问题时的比较如下表所示:算法名称时间复杂度优点缺点改进穷举法o (2n )最优解速度慢剪枝递归法o (2n )最优解空间消耗大用数组存动态规划法o (nm)最优解速度慢递归方程求解贪心法o(n log 2 n)不一定是最优解速度快可以作为启发.回溯法o (n2n )最优解速度慢改进剪枝分枝限界法o (n2n )最优解速度慢优化限界函数从计算复杂性理论看, 背包问题是np 完全问题。 半个多世纪以来, 该问题一直是算法与复杂性研究的热门话题。通过对0-1背包问题的算法

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论