1. 程式人生 > 實用技巧 >動態規劃(01揹包問題)

動態規劃(01揹包問題)

動態規劃(01揹包問題)

動態規劃演算法介紹

1) 動態規劃(Dynamic Programming)演算法的核心思想是:將大問題劃分為小問題進行解決,從而一步步獲取最優解的處理演算法

2) 動態規劃演算法與分治演算法類似,其基本思想也是將待求解問題分解成若干個子問題,先求解子問題,然後從這些子問題的解得到原問題的解。

3) 與分治法不同的是,適合於用動態規劃求解的問題,經分解得到子問題往往不是互相獨立的。 ( 即下一個子階段的求解是建立在上一個子階段的解的基礎上,進行進一步的求解 )

4) 動態規劃可以通過填表的方式來逐步推進,得到最優解.

技巧:用一個表格來寫出推算過程!!!

解決揹包問題

問題詳情:

揹包問題:有一個揹包,容量為 4 磅 , 現有如下物品

  1. 要求達到的目標為裝入的揹包的總價值最大,並且重量不超出
  2. 要求裝入的物品不能重複

思路分析和圖解

  1. 揹包問題主要是指一個給定容量的揹包、若干具有一定價值和重量的物品,如何選擇物品放入揹包使物品的價值最大。其中又分 01 揹包完全揹包(完全揹包指的是:每種物品都有無限件可用)
  2. 這裡的問題屬於 01 揹包,即每個物品最多放一個。而無限揹包可以轉化為 01 揹包。
  3. 演算法的主要思想,利用動態規劃來解決。每次遍歷到的第 i 個物品,根據 w[i]和 v[i]來確定是否需要將該物品放入揹包中。即對於給定的 n 個物品,設 v[i]、w[i]分別為第 i 個物品的價值和重量,C 為揹包的容量。再令 v[i][j] 表示在前 i 個物品中能夠裝入容量為 j 的揹包中的最大價值。

圖解:

基本公式:

  說明:(i是商品座標,j是揹包容量迭代的)

1   v[j][0]=v[0][j]=0
2   w[i]>j,v[i][j]=v[i-1][j]
3   j>w[i],v[i][j]=math.max(v[i-1][j],val[i]+v[i-1][j-w[i]]

程式碼實現:

package com.edu.algorithm.動態規劃;

/**
 * <p>
 * 使用動態規劃解決揹包問題[i是商品座標][j是揹包容量迭代的]
 * 公式:1.v[j][0]=v[0][j]=0
 *      2.w[i]>j,v[i][j]=v[i-1][j]
 *      3.j>w[i],v[i][j]=math.max(v[i-1][j],val[i]+v[i-1][j-w[i]])
 * </p>
 *
 * @作者 five-five
 * @建立時間 2020/9/1
 
*/ public class 揹包問題 { public static void main(String[] args) { int[] w = {1, 4, 3}; int[] val = {1500, 3000, 2000};//就是v[i] int max = 4; //建立二維陣列 int[][] v = new int[w.length+1][max+1];//可以不初始化第一行和第一列 for (int i = 0; i < v.length; i++) { v[i][0] = 0;//第一列設定為0 } for (int i = 0; i < v[0].length; i++) { v[0][i] = 0;//第一行設定為0 } //根據公式動態規劃 for (int i=1;i<v.length;i++){ for (int j=1;j<v[i].length;j++){ if (j<w[i-1]){//不是直接拿最大值來計算(逐一分析) v[i][j]=v[i-1][j]; }else { v[i][j]=Math.max(v[i-1][j],val[i-1]+v[i-1][j-w[i-1]]); } } } //列印一下 for (int[] i:v){ for (int j : i) { if(j==0){ System.out.print(j+"\t\t"); }else System.out.print(j+"\t"); } System.out.println(); } } }