一般背包问题(小数背包问题)——贪心算法解决方案

1、小数背包问题

      n种物品,1个背包,背包可容纳的总重量为c,每个物品i的价值为vi,重量为wi,如何选择物品,使得装入物品的总价值最大?这个是小数背包问题,不同于0-1背包问题,0-1背包问题中,整个物品不可分割,要么不装入要么全部装入。

2、贪心策略

      将物品按照性价比(单位重量价值)进行从大到小排序,将尽可能多的高性价比的物品装入背包,若将这种物品全部装入背包后,背包还有多余容量,则选择单位重量价值次高的并尽可能多地装入背包。如果最后一件物品无法全部装入,则计算可以装入的比例,然后按比例装入。

3、实战代码

(1)题目描述:

      设有5个物品,每个商品的价值分别是4, 6, 3, 5, 6,每个商品的重量分别是5, 4, 2, 6, 2,背包的总容量是10,求装包方案使得包中的商品价值最大。

(2)分析:

      需要定义一个类,类中封装物品编号num、商品价值value和商品重量weight,同时要定义排序规则。为什么要建个类呢?因为要对性价比排序,排序后各个物品的位置会发生变化,为了容易找到排序前的原始编号,所以定义了一个类,在类中封装了物品原始编号,使得不论怎么排序,原始编号都和对应的value、weight和性价比绑定。当然,乍一想感觉使用hashmap也可以实现排序后编号和性价比的绑定,把性价比当做map中的键key,编号作为map中的值,但是可能会出现相同性价比的问题,所以出现冲突时不宜区分。此处采用定义类的方式

import java.util.*;

public class Main {
    public static void main(String[] args) {
        // 因为性价比要作商,所以此处定义为double类型
        double[] value={4, 6, 3, 5, 6};
        double[] weight={5, 4, 2, 6, 2};
        double c = 10;

        int n = 5;
        List<Good> list = new ArrayList<>();
        for(int i = 0; i < n; i++){
            Good act = new Good(i+1,value[i],weight[i],value[i]/weight[i]);
              list.add(act);
        }
        //自定义排序规则,按照性价比从高到低排序
        Collections.sort(list, new Comparator<Good>() {
            // 此方法的返回值为int,但是性价比做差为double
            // 此处根据double的正负来返回1,-1和0
            @Override
            public int compare(Good o1, Good o2) {
                int result = 0;
                if(o2.getValueByWeight() - o1.getValueByWeight() > 0){
                    result = 1;
                }else if(o2.getValueByWeight() - o1.getValueByWeight() < 0){
                    result = -1;
                }
                return result;
            }
        });
        // 由于我想最终返回选择的物品编号和该物品的重量,所以此处定义了二维的list
        ArrayList<ArrayList<Double>> result = new ArrayList<ArrayList<Double>>();
        double currentWeight = 0;
        int index = 0;
        while(currentWeight < c && index < n){
            // 此物品可以完整的放入包中
            if(list.get(index).getWeight() + currentWeight <= c){
                ArrayList<Double> tem = new ArrayList<Double>();
                tem.add((double)list.get(index).getNum());
                tem.add(list.get(index).getWeight());
                result.add(tem);
                // 更新放入包中的总重量
                currentWeight+=list.get(index).getWeight();
                index++;
            }else{
                break;
            }
        }
        // 处理最优一个物品,最后一个物品可能不能完全放入包中,单独处理
        ArrayList<Double> last = new ArrayList<Double>();
        last.add((double)list.get(index).getNum());
        last.add((c - currentWeight));
        result.add(last);
        // 打印结果,由于result定义为double类型,导致打印的编号出现小数点,此处用了字符串截取
        for(ArrayList<Double> fac : result){
            System.out.println("所选物品是"+fac.get(0).toString().substring(0,1)+"--选择了"+fac.get(1));
        }
    }
}

class Good{
    int num;
    // 因为性价比要作商,所以此处定义为double类型
    double value;
    double weight;
    double valueByWeight;

    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public double getValue() {
        return value;
    }
    public void setValue(double value) {
        this.value = value;
    }
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
    public double getValueByWeight() {
        return valueByWeight;
    }
    public void setValueByWeight(double valueByWeight) {
        this.valueByWeight = valueByWeight;
    }
    public Good(int num, double value, double weight, double valueByWeight) {
        this.num = num;
        this.value = value;
        this.weight = weight;
        this.valueByWeight = valueByWeight;
    }
}

运算结果:

 

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值