JAVA实现0-1揹包问题

6、实验五0-1揹包问题

实验内容

内容:给定n种物品和一个揹包,物品i价值wi和重量vi已知,确定装入揹包的物品方案,使得包内物品总价值最大。

解题思路

原则:面对每个物品,只有选择拿与不拿两种选择,不能够选择装入物品的一部分,也不能装入同一物品多次。
解决方法:声明一个二维数组F[N + 1 , V + 1] ,F[i][v] 表示前i件物品恰放入一个容量恰为v的揹包可以获得的最大价值。通过分析可得出F[i , v]的计算方法,
1)当 v < W[i] 时,说明揹包容量不足以放下第i件物品,只能选择不拿,此时:在这里插入图片描述
2)当 v >= W[i] 时,这是揹包容量可以放下第i件物品,可以选择拿还是不拿,判断标准:拿这件物品是否能获取更大的价值。
如果拿,则在这里插入图片描述
如果不拿,则在这里插入图片描述

源代码

package e动态规划求解0_1揹包;

import java.util.Scanner;

public class Zero_oneKnapsack {

	int N, V;// N表示物体的个数,V表示揹包的载重
	private int[] weight;// 用于存储每个物体的重量,下标从1开始
	private int[] value;// 存储每个物体的收益,下标从1开始
	private int[][] F;// 二维数组,用来保存每种状态下的最大收益

	public static void main(String[] args) {
		Zero_oneKnapsack zok = new Zero_oneKnapsack();
		zok.init();
		zok.ZeroOnePackNonRecursive();
		zok.printResult(zok.N, zok.V);
	}

	/**
	 * @see 求解F这个二位数组
	 */
	public void ZeroOnePackNonRecursive() {
		// 对二维数组F进行初始化
		for (int j = 0; j <= V; j++) {
			F[0][j] = 0;
		}

		// 注意边界问题,i是从1开始的,j是从0开始的
		// 因为F[i - 1][j]中i要减1
		for (int i = 1; i <= N; i++) {
			for (int j = 0; j <= V; j++) {
				// 如果容量为j的揹包放得下第i个物体
				if (j >= weight[i]) {
					F[i][j] = Math.max(F[i - 1][j - weight[i]] + value[i], F[i - 1][j]);
				} else {
					// 放不下,只能选择不放第i个物体
					F[i][j] = F[i - 1][j];
				}
			}
		}

		// 打印所有结果,我们要求的是F[N][V]
		for (int i = 0; i <= N; i++) {
			for (int j = 0; j <= V; j++) {
				System.out.print(F[i][j] + "\t");
			}
			System.out.println();
		}
	}

	/**
	 * @see 求解F[n][m]这个最优值具体选取哪几样物品能获得最大价值
	 * @param n 表示前n个物体,n <= N
	 * @param v 表示揹包的容量,v <= V
	 */
	public void printResult(int n, int v) {
		boolean[] isAdd = new boolean[n + 1];

		for (int i = n; i >= 1; i--) {
			if (F[i][v] == F[i - 1][v])
				isAdd[i] = false;
			else {
				isAdd[i] = true;
				v -= weight[i];
			}
		}

		for (int i = 1; i <= n; i++) {
			if (isAdd[i] == true) {
				System.out.println("揹包里面有第 " + i + " 号物品");
			}
		}

		System.out.println("最优结果是:" + F[N][V]);
	}

	/**
	 * @see 初始化
	 */
	public void init() {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入物体个数、揹包的总空间:");
		N = sc.nextInt();
		V = sc.nextInt();

		// 下标从1开始,表示第1个物品
		weight = new int[N + 1];
		value = new int[N + 1];
		F = new int[N + 1][V + 1];// 注意是 N + 1,因为需要一个初始状态F[0][0],表示前0个物品放进空间为0的揹包的最大收益

		System.out.println("请依次输入每个物体的空间:");
		for (int i = 1; i <= N; i++) {
			weight[i] = sc.nextInt();
		}

		System.out.println("请依次输入每个物体的价值:");
		for (int i = 1; i <= N; i++) {
			value[i] = sc.nextInt();
		}
	}

}

运行截图

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章