详解部分背包问题原理与使用方法

部分背包问题(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背包 和 完全背包 中一些物品仅可选一次或仅可选若干次的限制,得到了更广泛的应用。但是,其贪心算法的策略也仅仅是将每个物品拆分为若干个可选部分,然后用贪心的策略尽可能多的选择单位价值最大的部分放入背包,其并不能得到最优解,因此仍旧有局限性。