贪心算法解决部分背包问题

问题:

假设商店中有 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);
		
		
	}

测试结果:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值