01分数背包

1.0-1问题 fractional knapsack

现在有m件物品,小偷有个最大承重为n的背包,单独的一件物品可拆分,求最后的可得的最大重量。

2.首先计算每个商品的单位价值,遵循贪心策略,小偷首先尽量多地拿走单位价值最高的商品,若该商品已经全部拿走而背包未满,将在剩余的商品中选择单位价值最高的拿走,以此类推,若剩余空间不够选择的商品全部拿走,则将剩余空间全部装上该商品的等重部分(即把该商品拿走与背包空间刚好相同的重量)。

Step1:首先计算每件商品的单位价值;

Step2:按照商品的单位价值从高到低排序;

Step3:依次按照单位价值从高到低选择商品,判断当前剩余空间能否全部装下该商品,若能则装下该商品,剩余空间减去该商品的空间,继续循环Step3,若不能,则把剩余空间装下该商品的等重部分,算法结束。

背包内物品的类:额外设计一个表示背包内物品的类是为了计算方便,并且在算法结束后可以知道每件物品往背包内所放的重量。

class Item implements Comparable<Item> {
	public String name;// 物品的名字
	public int weight;// 物品的重量
	public int value;// 物品的价值
	public double price;// 单位价值
	public double inputWeight;// 被放到背包中的重量

	public Item(String name, int weight, int value) {
		this.name = name;
		this.weight = weight;
		this.value = value;
		this.price = value/weight;
	}

	public int compareTo(Item vo) {
		return this.price >= vo.price ? -1 : 1;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getWeight() {
		return weight;
	}

	public void setWeight(int weight) {
		this.weight = weight;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public double getInputWeight() {
		return inputWeight;
	}

	public void setInputWeight(double inputWeight) {
		this.inputWeight = inputWeight;
	}

}


实现0-1分数背包的java代码:

/**
	 * 解决0--1分数背包问题。
	 * 
	 * @param list
	 *            传进来的是m件物品
	 * @param m
	 *            背包的最大重量
	 * @return 背包内所装物品的最大价值。
	 */
	public double fractionalKnapsack(ArrayList<Item> list,int m){
		double result = 0;//最后返回的价值
		/*首先计算每件商品的单位价值,按照商品的单位价值从高到低排序*/
		Collections.sort(list);
		int size = list.size();
		for(int i =0;i<size;i++){
			Item vo = list.get(i);
			if(m>=vo.getWeight()){//说明当前商品可以全部放进去
				m = m-vo.getWeight();
				result = result + vo.getValue();
				vo.setInputWeight(vo.getWeight());//设置该商品放到背包中的重量
			}else if(m>0){//可放到背包的最后一件商品需要拆分
				vo.setInputWeight(m);
				result = result + m*vo.getPrice();
				m = 0;
			}else{
				break;
			}
		}
		return result;
	}

例如求解某五件商品在背包承重为10 的时候可装的最大价值。

public static void main(String[] args){
		FractionalKnapsack test = new FractionalKnapsack();
		
		Item B0 = new Item("F",5,6);
		Item B1 = new Item("D",4,6);
		Item B2 = new Item("C",1,6);
		Item B3 = new Item("B",2,6);
		Item B4 = new Item("A",3,6);
		
		ArrayList<Item> list = new ArrayList<Item>();
		list.add(B0);
		list.add(B1);
		list.add(B2);
		list.add(B3);
		list.add(B4);
		
		/*求往背包承重为10的背包内可装的物品的最大价值*/
		double re = test.fractionalKnapsack(list, 10);
		System.out.println("往背包承重为10的背包内可装的物品的最大价值 re = "+re);
		System.out.println("依次选择的物品名称与放到背包内的重量");
		for(int i =0;i<list.size();i++){
			Item vo = list.get(i);
			System.out.println(vo.getName()+"  "+vo.getInputWeight());
		}
		
	}


代码执行结果如下:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值