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();
		}
	}

}

運行截圖

在這裏插入圖片描述

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