贪心算法 0-1背包问题 Java

贪心算法 0-1背包问题 Java

1、 贪心算法的思想:
假设一个问题比较复杂,暂时找不到全局最优解,我们可以考虑把原问题拆分成几个小问题(分而治之思想),分别求每个小问题的最优解,而把这些“局部最优解”叠起来,当作整个问题的最优解。
即:在每一步中,选择目前最优的策略,而不考虑全局是不是最优。
2、 顾眼前
遵循某种规则,不断(贪心地)选取当前最优策略,最终找到最优解。
难点:当前最优未必是整体最优;
3、 贪心算法三步走:

  1. 第一步:明确到底什么是最优解?
  2. 第二步:明确什么是子问题的最优解?
  3. 第三步:分别求出子问题的最优解再堆叠出全局最优解

0-1背包问题(每一个物品,要么选择,要么放弃)

问题描述:

有一个背包,最多能承载150斤的重量,现在有7个物品,重量分别为
[35, 30, 60, 50, 40, 10, 25],它们的价值分别为[10, 40, 30, 50, 35, 40, 30],如果是你的话,应该如何选择才能使得我们的背包背走最多价值的物品?

分析:对于此类问题,对于选择的物品有一个总和限制,比如重量,又希望另一个属性总和最大,比如价值。

贪心算法三步走:
 第一步:明确到底什么是最优解?
即在重量限制范围内,价值最大的选择。
 第二步:明确什么是子问题的最优解?
子问题定义?认为每次都尽量选择当前价值最高的物品,这就是“局部最优解”。
 第三步:分别求出子问题的最优解再堆叠出全局最优解?

  1. 子问题定义1:使用价值最高的作为标准:
    重量:[35, 30, 60, 50, 40, 10, 25]
    价值:[10, 40, 30, 50, 35, 40, 30]
    选择:
    最终的总重量为:50+30+10+40=130
    最终的总价值为:50+40+40+35=165

子问题定义2:将当前物品中重量最小的作为最优解;
重量:[35, 30, 60, 50, 40, 10, 25]
价值:[10, 40, 30, 50, 35, 40, 30]
选择:
最终的总重量为:10+25+30+35+40=140
最终的总价值为:40+30+40+10+35=155

  1. 子问题定义3:每次选择“价值密度”最高的物品;
    重量:[35, 30, 60, 50, 40, 10, 25]
    价值:[10, 40, 30, 50, 35, 40, 30]
    价值密度:[10/35,40/30,30/60,50/50,35/40,40/10,30/25]
    选择:
    最终的总重量为:10+30+25+50+35=150
    最终的总价值为:40+40+30+50+10=170
    总结:单位密度这个策略比之前的价值策略和重量策略都要好。
    特定的环境,特定的定义方式,每种定义方式只适合特定条件最优。

代码:

import java.util.Scanner;

public class a_0_1背包问题
{
	public static int[] zhonliang = { 35, 30, 60, 50, 40, 10, 25 };
	public static int[] jiazhi = { 10, 40, 30, 50, 35, 40, 30 };

	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int zonzhong=sc.nextInt();//总重量
		
		//调用函数
		maxJiaZhi(zonzhong);		
	}

	//求价值
	private static void maxJiaZhi(int zonzhong) {
		//存储累加的重量和价值
		int maxZhong=0;
		int maxJia=0;
		//存放密度
		double[] midu=new double[7];
		//存放索引的数组
		int [] index=new int[7];
		for (int i = 0; i < midu.length; i++)
		{
			midu[i]=(double)jiazhi[i]/zhonliang[i];	
			index[i]=i;
		}
		//冒泡排序
		for (int i = 0; i < midu.length-1; i++)
		{
			for (int j = 0; j < midu.length-1-i; j++)
			{
				if (midu[j]<midu[j+1])
				{
					double temp=midu[j];
					midu[j]=midu[j+1];
					midu[j+1]=temp;
					
					//索引跟着交换
					int temp1=index[j];
					index[j]=index[j+1];
					index[j+1]=temp1;
				}
			}
		}
		
		//计算最优解
		for (int i = 0; i < index.length; i++)
		{
			if (zhonliang[index[i]]<=zonzhong)
			{
				maxZhong+=zhonliang[index[i]];
				maxJia+=jiazhi[index[i]];
				zonzhong-=zhonliang[index[i]];
			}
		}
		
		System.out.println("总重量:"+maxZhong);
		System.out.println("总价值:"+maxJia);
	}

}

输入样例:

150

输出样例:

总重量:150
总价值:170
  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值