背包问题是一个很经典的问题,主要的意思是:给一个容量为S的背包和一些物品,每件物品有自己的重量Wi和自己的价值Vi,如何选取合适的物品装进背包里,使得背包中物体的价值最大。
背包问题有两种基本的分类,一个是连续或者说可分的背包问题,意思是说每件物体是可以分割的,想装多少都可以。这个问题的解法比较简单,用贪心法,对所有物体求一下单位价值,然后取单位价值最大的往背包里装,单位价值最大的用完了再装次大的,直到背包装满为止。
另一类是非连续或者说不可分的背包问题,就是每个物体的重量和价值确定后不能再继续分割了。这样的话就不存在贪心策略了,因为如果每次按总价值最大的选,可能会因为占用背包容量太多而导致并不是最优策略。对于这样的问题,可以采用动态规划来做。
设物品的集合为O={(w1,v1),(w2,v2)...(Wn,Vn)},设只取前n件物体能得到的最大价值为f(S,n),S为背包的容量,则可以对第n件物体进行讨论:如果最后的结果中包含第n件物体,那么只需要考虑前n-1件物体装在S-Vn的背包里的最大价值; 如果最后的结果中不包含第n件物体,那么只需要考虑前n-1件物体装在S的背包里的最大价值.即
f(S,n)= max{ f(S-Wn),n-1)+Vn, f(S,n-1) }
这样问题的规模变小了,结构却是不变的,最终就可以求解.边界条件是:如果背包空间变为0或负数,那么最大价值就是0.即
f(0,i)=0;
另外,如果不考虑往背包里放任何东西,则背包的价值设为负无穷.
这个类型的问题还可以扩展,将一个一个的物体改为一类物体,每类物体的数量有一个最大限度.
这样的问题,其实只要将一类物体扩展成一个一个的就好了.比如对A类物体最多有5个,B类物体最多有3个,那么相当于集合S中有5个A和3个B,本质上是不变的.直接用上述算法即可.
如果每类物体的数量是无限多的,但由于背包的空间有限,所以能装的物体的数量还是有上限的.
以上是经典的背包问题.今天我看<<编程之美>>,里面有一个问题是:公司要为员工准备各种饮料,每种饮料有不同的满意度,如何确定使总的满意度最大的供货方案.很显然这就是背包问题,不过这个问题有一个特别的地方是,题目说各种饮料的容量都是2的n次幂.那么这个2的n次幂的约束对这个题目有什么影响呢?
其实是这样的,本来这是一个不连续的背包问题,只能用动态规划而不能用贪心法来做.但是加入了所有容量都是2的n次幂的条件后就可以用贪心法了.
如果我们把总的容量S按2的幂级数展开,那么最后一级势必只能容量为用2的0次幂的饮料来装,而2的1次幂对应的一级,可以用容量为2的1次幂的饮料,或者用两个容量为2的0次幂的饮料来装.它们的满意度(价值)是很好比较的,只需要选价值最大的那种方案即可. 那么更高次幂对应容量更大的饮料,也只需要选择满意度最大的方案即可了.这样就可以用贪心法来实现了.
看了这个题目之后我就想,这个问题是介于连续和不连续的背包问题之间的,可以认为是半连续的,所以可以用贪心法来做.那么到底满足什么条件的背包问题可以用贪心法呢?
显然如果物体的重量都是某个数的幂级数时是可以的,除此之外呢?
我还没有想出来.