JAVA实现贪心算法解决背包问题

9、实验八贪心算法解决背包问题

实验内容

使用重量贪心、价值贪心和价值密度贪心三种贪心准则,求解背包问题。
本次实验,自行设计输入提示、输入数据形式、结果输出样式,需要认真思考,都需要用户输入哪些基本数据、最终需要显示哪些结果信息,才能使用户根据结果提示,正确完成物品的全部存放过程。(本次实验报告批改时,这些都作为采分点)

解题思路

重量贪心:从剩下的物品中,选出可装入背包的重量最小的物品。
价值贪心:从剩下的物品中,选出可装入背包的价值最大的物品。
价值密度贪心:从剩下的物品中,选出可装入背包的值最大的物品。
以价值密度贪心作为例子,其他两种类似:
1、计算每种物品单位的价值
2、将尽可能多的单位重量价值最高的物品装入背包
3、若将这种物品全部装入背包后,背包内物品的总重量未超过背包的容量C,则选择单位重量价值次高的物品并尽可能多地装入。

源代码

package h贪心算法解决背包问题;

import java.util.Scanner;

/**
 * @author Draco
 * @see 贪心准则:价值贪心
 * @version 1.0
 * @date-time 2020-06-08 - 下午12:31:11
 */
public class Value {

	public static Scanner scanner = new Scanner(System.in);
	public static int n;// 物品个数
	public static float C;// 背包容量
	public static float[] weight;// 重量数组
	public static float[] value;// 价值数组
	// 拷贝的目的是,在后面对重量数组和价值数组进行了排序,打乱了原来的数组顺序,故先拷贝出来一份。
	public static float[] v;// 拷贝一份价值数组
	public static float[] w;// 拷贝一份重量数组
	public static float[] add;// 放入的比例数组

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		System.out.print("请输入物品的个数:");
		n = scanner.nextInt();
		weight = new float[n];
		value = new float[n];
		v = new float[n];
		w = new float[n];
		System.out.print("请输入背包的容量:");
		C = scanner.nextFloat();
		System.out.println("请输入物品的重量和价值:");
		for (int i = 0; i < n; i++) {
			weight[i] = scanner.nextFloat();
			value[i] = scanner.nextFloat();
			// 进行拷贝
			v[i] = value[i];
			w[i] = weight[i];
		}
		addBag();
		float total = totalValue();
		System.out.println("背包的总价值为:" + total);

	}

	/**
	 * @see 计算总价值
	 * @return 返回总价值
	 */
	public static float totalValue() {
		float total = 0;
		for (int i = 0; i < n; i++) {
			total += add[i] * value[i];
		}
		return total;
	}

	/**
	 * @see 计算物品放入的比例,放入到add数组中
	 */
	public static void addBag() {
		add = new float[n];
		// 给价值数组进行排序,价值大的在前面
		int index[] = Arraysort(value);// 对value进行了排序
		for (int i = 0; i < n; i++) {
			if (w[index[i]] <= C) {
				// 加入背包中
				add[index[i]] = 1;
				C = C - w[index[i]];
			} else {
				// 按比例加入背包中
				add[index[i]] = C / w[index[i]];

			}
		}
		System.out.print("放入重量比例:");
		for (float i : add) {
			System.out.print("\t" + i);
		}
		System.out.println();
		System.out.print("单个物品价值:");
		for (float i : value) {
			System.out.print("\t" + i);
		}
		System.out.println();
	}

	/**
	 * @see 将传进来的数组进行排序,小的在前面
	 * @param arr
	 * @return 返回原来数组的下标
	 */
	public static int[] Arraysort(float[] arr) {
		float temp;
		int index;
		int k = arr.length;
		int[] Index = new int[k];
		for (int i = 0; i < k; i++) {
			Index[i] = i;
		}

		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < arr.length - i - 1; j++) {
				if (arr[j] < arr[j + 1]) {
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;

					index = Index[j];
					Index[j] = Index[j + 1];
					Index[j + 1] = index;
				}
			}
		}
		return Index;
	}

}

package h贪心算法解决背包问题;

import java.util.Scanner;

/**
 * @author Draco
 * @see 贪心准则:重量贪心
 * @version 1.0
 * @date-time 2020-06-08 - 下午12:30:28
 */
public class Weight {
	public static Scanner scanner = new Scanner(System.in);
	public static int n;// 物品个数
	public static float C;// 背包容量
	public static float[] weight;// 重量数组
	public static float[] value;// 价值数组
	// 拷贝的目的是,在后面对重量数组和价值数组进行了排序,打乱了原来的数组顺序,故先拷贝出来一份。
	public static float[] v;// 拷贝一份价值数组
	public static float[] w;// 拷贝一份重量数组
	public static float[] add;// 放入的比例数组

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		System.out.print("请输入物品的个数:");
		n = scanner.nextInt();
		weight = new float[n];
		value = new float[n];
		v = new float[n];
		w = new float[n];
		System.out.print("请输入背包的容量:");
		C = scanner.nextFloat();
		System.out.println("请输入物品的重量和价值:");
		for (int i = 0; i < n; i++) {
			weight[i] = scanner.nextFloat();
			value[i] = scanner.nextFloat();
			// 进行拷贝
			v[i] = value[i];
			w[i] = weight[i];
		}
		addBag();
		float total = totalValue();
		System.out.println("背包的总价值为:" + total);

	}

	/**
	 * @see 计算总价值
	 * @return 返回总价值
	 */
	public static float totalValue() {
		float total = 0;
		for (int i = 0; i < n; i++) {
			total += add[i] * value[i];
		}
		return total;
	}

	/**
	 * @see 计算物品放入的比例,放入到add数组中
	 */
	public static void addBag() {
		add = new float[n];
		// 给重量数组进行排序,重量小的在前面
		int index[] = Arraysort(weight);// 对weight进行了排序
		for (int i = 0; i < n; i++) {
			if (w[index[i]] <= C) {
				// 加入背包中
				add[index[i]] = 1;
				C = C - w[index[i]];
			} else {
				// 按比例加入背包中
				add[index[i]] = C / w[index[i]];

			}
		}
		System.out.print("放入重量比例:");
		for (float i : add) {
			System.out.print(i + "\t");
		}
		System.out.println();
		System.out.print("单个物品价值:");
		for (float i : value) {
			System.out.print(i + "\t");
		}
		System.out.println();
	}

	/**
	 * @see 将传进来的数组进行排序,小的在前面
	 * @param arr
	 * @return 返回原来数组的下标
	 */
	public static int[] Arraysort(float[] arr) {
		float temp;
		int index;
		int k = arr.length;
		int[] Index = new int[k];
		for (int i = 0; i < k; i++) {
			Index[i] = i;
		}

		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < arr.length - i - 1; j++) {
				if (arr[j] > arr[j + 1]) {
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;

					index = Index[j];
					Index[j] = Index[j + 1];
					Index[j + 1] = index;
				}
			}
		}
		return Index;
	}
}

package h贪心算法解决背包问题;

import java.util.Scanner;

/**
 * @author Draco
 * @see 贪心准则:价值密度贪心
 * @version 1.0
 * @date-time 2020-06-08 - 上午11:02:59
 */
public class Density {
	public static float C1 = 0;// 总价值

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner = new Scanner(System.in);
		System.out.print("请输入物品的个数:");
		int n = scanner.nextInt();
		System.out.print("请输入背包的容量:");
		float C = scanner.nextFloat();
		System.out.println("请输入物品的重量和价值:");
		float[] wi = new float[n + 2];
		float[] vi = new float[n + 2];
		float[] x = new float[n + 2];
		float[] v2 = new float[n + 1];
		float[] w2 = new float[n + 1];
		for (int i = 1; i <= n; i++) {
			wi[i] = scanner.nextFloat();
			vi[i] = scanner.nextFloat();
			v2[i] = vi[i];
			w2[i] = wi[i];
		}
		Density test = new Density();
		test.Knapsack(n, C, vi, wi, x, v2, w2);
		System.out.println();
		System.out.print("单个物品价值:");
		for (int i = 1; i <= n; i++) {
			System.out.print("\t" + v2[i]);
		}
		System.out.println();
		System.out.println("背包的总价值为:" + C1);
	}

	/**
	 * @see 将物品按价值比从大到小排放在数组
	 * @param n 物品个数
	 * @param v 价值数组
	 * @param w 重量数组
	 */
	void Sort(int n, float[] v, float w[]) {
		float temp1;
		float temp2;
		for (int i = 1; i <= n; i++) {
			for (int s = 1; s <= i; s++) {
				if (v[i] / w[i] > v[s] / w[s]) {
					temp1 = v[s];
					temp2 = w[s];
					v[s] = v[i];
					w[s] = w[i];
					v[i] = temp1;
					w[i] = temp2;

				}
			}
		}
	}

	void Knapsack(int n, float W, float v[], float w[], float x[], float v2[], float w2[]) {
		Density a = new Density();
		a.Sort(n, v, w);
		int i;
		for (i = 1; i <= n; i++)
			x[i] = 0;
		float c = 0;

		for (i = 1; i <= n; i++) {
			if (w[i] > W)
				break;// 如果物品的重量大于背包剩余容量,停止放入整个物品
			for (int t = 1; t <= n; t++) {
				if (w[i] == w2[t] && v[i] == v2[t])// 将放入了的物品标记为1
					x[t] = 1;
			}
			W -= w[i];
			c += v[i];
		}
		if (i <= n) {
			for (int q = 1; q <= n; q++) {
				if (w[i] == w2[q] && v[i] == v2[q]) {
					x[q] = W / w[i];// 放入部分物品记录放入的比例
					c += x[q] * v[i];
				}
			}

		}
		System.out.print("放入重量比例:");
		for (int k = 1; k <= n; k++) {
			System.out.print("\t" + x[k]);
		}
		C1 = c;
	}

}

运行截图

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 9
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值