揹包問題----動態規劃

i學學學學學習發表於2020-11-24

一、動態規劃

動態規劃演算法的關鍵在於解決冗餘,這是動態規劃演算法的根本目的。把問題分解成若干個子問題,然後記錄下每個子問題的解,避免重複計算,再從眾多子問題中選出最優解。
點選這檢視上一篇動態規劃詳解

問題描述:給定 n 個重量為w1,w2···wn,價值為v1,v2···vn,揹包的承重量為 W 。

揹包問題是給定 W 重量的揹包裝入儘可能高價值的物品。F(i,w):前 i 個物品,當前揹包還可以裝w重量。

我們可以把前 i 個物品中放入重量為 W 的揹包中價值最大化問題分解成兩個問題:

  1. 裝入揹包的物品不包括第 i 個物品,F(i , w) = F(i -1 , w);
  2. 裝入揹包的物品包括第 i 個物品,F(i , w) = F(i -1 , w - wi) + vi;

現在假設有四個物品,重量分別為 2, 1, 3, 2; 價值為 12, 10, 20, 15; 給定一個承重為 W = 5 的揹包,求裝入物品的最大價值是多少?

在這裡插入圖片描述
首先,根據以上步驟,可以將問題分解為:

  1. F(4, 5) = max{F(3, 5), F(3, 3) + 15 };
  2. F(3, 5) = max{F(2, 5), F(2, 2) + 20 };
  3. F(3, 3) = max{F(2, 3), F(2, 0) + 20 };
  4. F(2, 5) = max{F(1, 5), F(1, 4) + 10 };
    .
    .
    .
  5. F(0, 5) = 0;
  6. F(i, 0) = 0;

同樣的,我們需要定義一個二維陣列來儲存每一個子問題的解,避免重複計算。

在這裡插入圖片描述

程式碼如下:

public class Main{
	static int[] v = {12, 10, 20, 15};
	static int[] w = {2, 1, 3, 2};
	public static void main(String[] args){
	int W = 5;
	int[][] F = new int[v.length][W];
	Func(F, v.length-1, W-1);
	System.out.println(F[v.length-1][W-1]);
	}
	/**
	 * 遞迴三部曲:
	 * 1.確定引數與返回型別
	 * 2.確定終止條件
	 * 3.確定單體迴圈
	 * @param Ye
	 * @return
	 */
	public static int Func(int[][] F,int i,int W)
	{
		if(i < 0 || W < 0) return 0;
		if(F[i][W] != 0) return F[i][W];
		if((W-w[i]) >= -1)
			F[i][W] = Math.max(Func(F,i-1, W), Func(F,i-1, W-w[i]) + v[i]);
		else
			F[i][W] = Func(F,i-1, W);
		return F[i][W];
	}
}

相關文章