问题:
假设商店中有 3 种商品,它们各自的重量和收益是:
商品 1:重量 10 斤,收益 60 元;
商品 2:重量 20 斤,收益 100 元;
商品 3:重量 30 斤,收益 120 元。
对于每件商品,顾客可以购买商品的一部分(可再分)。一个小偷想到商店行窃,他的背包最多只能装 50 斤的商品,
如何选择才能获得最大的收益呢?
贪心算法的思想:
算法在每一步都采用最优的解,每一步的选择都是当前的最优解。
注意:贪心算法虽然每一步都是最优的,但是算法并不一定是最优的。
解题思路:
贪心算法追求局部最优,那么在部分背包问题中,我们要追求最大收益就要先装价值最高的商品,再装剩下商品中价值最高的,直至装满或没有能装的商品。
具体步骤:
1、先计算商品的价值,在按照商品的价值从大到小进行排序
2、按商品价值从大到小将商品装入背包,直至装满。
3、装载商品时需判断商品能否完整装下,能则装入所有的该商品并计算背包内商品总价值,不能则装入背包剩余容量的该商品,并计算背包内商品的总价值。
//根据收益率对商品进行排序
//weight[] 商品对应的重量,price[] 商品对应的价格,它们的下标表示商品
public static void sort(double[] weight,double[] price) {
//商品的种类数
int quantity = weight.length;
//商品对应的收益率
double income[] = new double[quantity];
//求出所有商品对应的收益率
for(int i = 0;i < weight.length;i ++) {
income[i] = price[i]/weight[i];
}
//根据受益率进行从大到小的排序(此处采用冒泡排序)
for(int i = 0;i < quantity;i ++) {
for(int j = i+1;j < quantity;j ++) {
if(income[i] < income[j]) {
//交换重量
double tmp = weight[i];
weight[i] = weight[j];
weight[j] = tmp;
//交换价格
tmp = price[i];
price[i] = price[j];
price[j] = tmp;
}
}
}
}
//装载商品的计算
//weight[]商品重量,price[]商品价格,backpack[],backpackW背包的剩余空间
public static void calculate(double[] weight,double[] price,double[] backpack,double backpackW) {
//根据收益率将商品进行从大到小排序
sort(weight,price);
int i = 0;
//背包内商品的总价值
double allPrice = 0;
//将商品装入背包
//装不满则继续装,装满结束循环
while(backpackW > 0) {
if(weight[i] <= backpackW) {//商品能完整装下
//商品存入背包
backpack[i] = weight[i];
//背包容量减少
backpackW -= weight[i];
//计算背包内商品总价值
allPrice += price[i];
System.out.println("装入"+i+"号商品,重量为:"+backpack[i]+",该商品总价格为:"+price[i]);
}else {//商品不能完整装下
backpack[i] = backpackW;
backpackW -= backpackW;
//计算背包内商品总价值
allPrice += backpack[i]*(price[i]/weight[i]);
System.out.println("装入"+i+"号商品,重量为:"+backpack[i]+",该商品总价格为:"+backpack[i]*(price[i]/weight[i]));
}
i++;
}
//输出背包内商品的总价值
System.out.println("背包内商品的总价值为:"+allPrice);
}
测试结果: