动态规划DP——01背包问题
01 背包問題
??今天在算法課上講解了動態規劃算法,其中講到了01背包問題。這是一種典型的動態規劃問題,于是下課之后我使用java進行了相對應的代碼實現。動態規劃求解具有以下的性質:
1.最優子結構性質:最優解包含了其子問題的最優解,不是合并所有子問題的解,而是找最優的一條解線路,選擇部分子最優解來達到最終的最優解。
2.子問題重疊性質:先計算子問題的解,再由子問題的解去構造問題的解(由于子問題存在重疊,把子問題解記錄下來為下一步使用,這樣就直接可以從備忘錄中讀取)。其中備忘錄中先記錄初始狀態。
題目描述
現有一個容量大小為V的背包和N件物品,每件物品有兩個屬性,體積和價值,請問這個背包最多能裝價值為多少的物品?
輸入描述
第一行兩個整數V和n。 接下來n行,每行兩個整數體積和價值。1≤N≤1000,1≤V≤20000。 每件物品的體積和價值范圍在[1,500]。輸出描述
輸出背包最多能裝的物品價值。輸入
6 3 3 5 2 4 4 2輸出
9??首先我們來分析這個問題,它不同于背包問題的是一個物品只有放入背包和不放入背包兩種狀態,所以我們將這兩種狀態可以稱之為01。這種問題一般是不能使用貪心算法進行解決的,我們通常使用動態規劃的方法進行求解。因為這類問題具有最優子結構性質,也就是說整個問題的最優解一定包含了子問題的最優解,于是乎我們就可以在求解子問題的同時將解進行記錄(備忘錄的思想)從而降低整個問題求解的時間復雜度。
??依據輸入樣例我們可以對該問題進行分析,背包的容量為6,物品總共有3個。我們不妨記函數 V(i,j) 代表整個背包存放物品的價值,其中 i 表示第幾個物品,j 表示背包的體積。記volume(i) 為第i個物品的體積,記value(i) 為第i個物品的價值。我們可以得到狀態轉移方程:
當volume(i) > j 時: V(i,j) = V(i-1,j) 此時背包放不下該物品
當volume(i) <= j 時: V(i,j) = max{V(i-1,j) , V(i-1,j-volume(i))+value(i)}
此時背包容量足夠,在不放該物品 & 放該物品并不放上一個物品當中取最大值。
??我們可以用表格的形式來具體描述這個二維數組, 首先我們需要將數據初始化,也就是將第一行第一列賦值為0,因為無論是背包容量為0,還是物品為第0個(我們約定 i 從 1 開始)
當j=3 也就是背包容量為3時 volume(1)=j v(i,j)=max{0,5}
當i=2 j=5此時物品2 volume(1) < j v(i,j)=max{v(1,5),v(1,3)+4}
進一步完成表格
于是這個01背包問題也就轉變成了一個二維數組的填數字問題,我們只需要按照狀態方程去判斷進行計算填滿表格,就能夠得到所背包的最大價值。
實現代碼
import java.util.*;public class Main { public static void main(String[] args) {Scanner sc = new Scanner(System.in);int v = sc.nextInt();//背包容量int n = sc.nextInt();//商品的個數Map<Integer,Map<Integer,Integer>> map = new HashMap<>();//容器用于存儲商品鍵值對for(int i=0; i<n; i++){int key = i+1;HashMap<Integer,Integer> value = new HashMap<>();value.put(sc.nextInt(),sc.nextInt());map.put(key,value);}Integer max = findMax(map,v,n);System.out.println(max); } private static Integer findMax(Map<Integer, Map<Integer, Integer>> map, int v, int n) {//數據初始化int[][] arr = new int[n+1][v+1];for(int i=0;i<v+1;i++){arr[0][i]=0;}for(int i=0;i<n+1;i++){arr[i][0]=0;}int max = 0;//背包最大值int pack = v;//當前背包容量Set<Map.Entry<Integer, Map<Integer, Integer>>> entries = map.entrySet();for (Map.Entry<Integer, Map<Integer, Integer>> entry : entries) {int i = entry.getKey();//當前商品編號Map<Integer,Integer> Value =entry.getValue();//當前商品價值Set<Map.Entry<Integer, Integer>> entries1 = Value.entrySet();int tiji ;//當前商品體積int value;//當前商品價值for (Map.Entry<Integer, Integer> integerIntegerEntry : entries1) {tiji = integerIntegerEntry.getKey();value = integerIntegerEntry.getValue();for (int j = 1; j < v + 1; j++) {if (j < tiji) {arr[i][j] = arr[i - 1][j];} else {arr[i][j] = Math.max(arr[i - 1][j], arr[i - 1][j - tiji] + value);if (max <= arr[i][j]) {max = arr[i][j];}}}}}return max; } }總結
以上是生活随笔為你收集整理的动态规划DP——01背包问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图层颜色叠加
- 下一篇: django分页、查询