问题描述
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问:应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
算法设计分析
从所有的物品中选取若干将它们装进背包,在满足限制条件的情况下,获得最大的收益。既然要选择一个对象的子集,解空间就应该组织成子集树结构。要设计的递归算法使用深度优先搜索子集树:
对于左孩子,满足限制条件即可;对于右孩子,需要利用界定函数计算此节点的收益上限,即当前节点的收益加上还未考察的对象的收益是否超过当前最优解的收益。如果不是,则不需要搜索右子树。
下面考虑界定函数:
实例:0/1背包问题,当n=3时,w={20,15,15}, p={40,25,25}, c=30,收益密度{2, 5/3, 5/3}。
当以收益密度递减顺序装包时,首先选择对象1,此时剩余容量为10,只能装下2/3的对象2,则生成的解为{1, 2/3, 0},总收益为170/3,虽然这个解不可行(装包量必须是0或1),但可以作为一个界定值,因为它不小于任何一个可行解包括最优解。所以,将对象按收益密度递减顺序排列,能够容易得到界定函数。
算法步骤:
1、将背包装载对象按收益密度递增顺序排序;
2、对于当前节点currentLevel,判断是否大于对象数,若否,继续下面步骤,反之,算法终止;
3、检查左孩子,若不超过总的容量,左孩子可行,递归左子树;
4、检查右孩子,若有孩子的收益上限大于当前最优解的最大收益,左孩子可行,递归右子树;
上述实例的回溯过程如图:
A ——> B ——> E ——> B ——> A ——> C ——> F ——> L ——> F ——> C ——> A
C++实现
定义一个结构element
,其数据成员是