部分背包问题(Fractional Knapsack Problem)也叫做分数背包问题,是指:有一个背包,最多能承载物品的重量为W。现在有n个物品,每个物品的重量为$w_i$,价值为$v_i$。要求选出若干件物品放入这个背包中,使得选入背包中的物品总重量不超过W,且让选入的物品的总价值最大。
相比于 01背包 和 完全背包,部分背包问题可以选择一件物品的部分使用。
使用方法:
1.将所有物品按照单位价值(即价值/重量)从大到小排序。
2.依次考虑每个物品,如果该物品重量小于等于背包的剩余容量,就将整个物品放进去;否则,计算能放多少,放入即可。
举例说明:
问题1:假设有一个背包,容量为50kg。现在有如下物品,求最大的价值。
序号 | 名称 | 重量(kg) | 价值(元) |
---|---|---|---|
1 | 牛奶 | 10 | 60 |
2 | 面包 | 20 | 100 |
3 | 鸡蛋 | 30 | 120 |
4 | 薯条 | 40 | 160 |
5 | 纸巾 | 50 | 200 |
解答:首先,计算每个物品的单位价值。得到如下表格。
序号 | 名称 | 重量(kg) | 价值(元) | 单位价值(元/kg) |
---|---|---|---|---|
1 | 牛奶 | 10 | 60 | 6 |
2 | 面包 | 20 | 100 | 5 |
3 | 鸡蛋 | 30 | 120 | 4 |
4 | 薯条 | 40 | 160 | 4 |
5 | 纸巾 | 50 | 200 | 4 |
然后,按照单位价值从大到小排列。得到如下顺序:1,2,3,4,5。
接着,从序号1开始,尽可能多的将物品放入背包中。因为容量为50kg,所以可以放入5kg(即1/2个)的牛奶,剩余40kg。接着考虑物品2,可以放入完整的20kg。剩余20kg。继续,放入3kg(即1/10个)的鸡蛋,剩余17kg。放入8kg(即1/5个)的薯条,剩余9kg。放入剩余的9kg纸巾。至此,背包装满。
因此,最大的价值为601/2+205+301/10+401/5+50=390元。
问题2:假设有一个背包,容量为12kg。现在有如下物品,求最大的价值。
名称 | 重量(kg) | 价值(元) |
---|---|---|
牛奶 | 3 | 10 |
面包 | 4 | 15 |
橙汁 | 2 | 8 |
香蕉 | 1 | 5 |
雪碧 | 1 | 4 |
巧克力 | 6 | 12 |
解答:由于本例背包容量很小,使用 01背包 和 完全背包 不方便,因此使用部分背包问题求解。
首先,计算每个物品的单位价值。得到如下表格。
名称 | 重量(kg) | 价值(元) | 单位价值(元/kg) |
---|---|---|---|
牛奶 | 3 | 10 | 3.33 |
面包 | 4 | 15 | 3.75 |
橙汁 | 2 | 8 | 4 |
香蕉 | 1 | 5 | 5 |
雪碧 | 1 | 4 | 4 |
巧克力 | 6 | 12 | 2 |
然后,按照单位价值从大到小排列。得到如下顺序:4,3,2,1,5,6。
接着,从序号4开始,尽可能多的将物品放入背包中。因为容量为12kg,所以可以放入12kg的香蕉,剩余11kg。继续,放入剩余的1kg雪碧。至此,背包装满。
因此,最大的价值为5*5+4= 29元。
总结:部分背包问题解决了 01背包 和 完全背包 中一些物品仅可选一次或仅可选若干次的限制,得到了更广泛的应用。但是,其贪心算法的策略也仅仅是将每个物品拆分为若干个可选部分,然后用贪心的策略尽可能多的选择单位价值最大的部分放入背包,其并不能得到最优解,因此仍旧有局限性。