蓝桥杯 背包问题 贪心算法 Java

  本文为博主原创文章,未经允许禁止转载。http://blog.csdn.net/icydate/article/details/79589590

问题描述:

设有n个物体和一个背包,物体i的重量为wi ,价值为vi ,背包的容量为C.若将物体i的xi部分(1≤i≤n, 0≤xi≤1)装入背包,则具有

价值为vi xi. 目标是找到一个方案,使放入背包的物体总价值最高.

解题思路:

首先,这里的物品是可以拆分的,所以我们要尽可能的放单位价值最高的物品进去

1、先计算所有物品的单位价值

2、取价值最高者,放入背包

3、计算背包剩余空间

4、在剩下的物品中,取价值最高的,放入背包,直到背包装满,或物品装完。

例子:

物品价值{p1,p2,p3}={25,24,15};物品重量{w1,w2,w3}={18,15,10}

简单计算一下单位价值,发现{v1,v2,v3}={1.3888,1.6,1.5};

所以第二个物品装得越多,总价值越高,如下表


接下来是代码

public class GreedySelector {
	public static void main(String[] args) {
		int n = 3; //物品数量
		float m = 20; //背包总容量
		float[] p = {25,24,15}; //物品价值
		float[] w = {18,15,10}; //物品重量
		float[] x = {1,1,1}; //每个物品装入背包的量
		
		test(n, m, p, w, x);
	}
	
	public static void test(int n,float m,float[] p,float[] w,float[] x){
		float[] value = new float[n]; //物品单位价值
		float sum = 0; //用于存放装入的总价值
		for(int i = 0;i<n;i++){
			value[i]=p[i]/w[i]; //将计算好的物品单位价值放入数组
		}
		//降序排序,将物品价值,物品重量都以单位价值从大到小排序
		for(int i = 0;i < n;i++){
			for(int j = i;j < n;j++){
				//第一轮,将数组第一位与每一位比较,每次比较把值大的放入第一位,能保证循环结束后第一位一定是最大的。
				//第二轮,就从数组第二位开始,保证第二位是剩余数中最大的,以此达到降序排列
				//将物品价值,物品重量降序排序,保证之后的循环一定是单位价值高的物品先装入
				if(value[i] < value[j]){
					float temp = value[i];
					value[i] = value[j];
					value[j] = temp;
					float temp2 = p[i];
					p[i] = p[j];
					p[j] = temp2;
					float temp3 = w[i];
					w[i] = w[j];
					w[j] = temp3;
				}
			}
		}
		//初始化,表示所有东西都没装
		for(int i = 0;i < n;i++){
			x[i]=0;
		}
		int index = 0; //用于存放最后一个没装入的物品索引
		//先将单位价值最高的物品放入书包
		for(int i = 0;i < n;i++){
			index = i;
			if(w[i]>m){ //当当前物品重量大于背包剩余重量时结束循环
				break;
			}
			x[i]=1; //代表全部装入
			m -= w[i]; //减去已转入的物品重量
		}
		//可能存在最后一个物品总重量已经大于剩余重量,但能够装一部分进去的情况
		if(index < n){
			x[index]=m / w[index]; //计算其能装入多少
		}
		//计算总价值
		for(int a = 0;a <= index;a++){
			sum += x[a]*p[a]; //装入的比例*该物品的总价值
		}
		System.out.println("贪心算法所计算的总价值为:" + sum);
	}
}
运行一下,结果与表格里是一样的



猜你喜欢

转载自blog.csdn.net/icydate/article/details/79589590