文字介紹解決背包問題
假設山洞里共有a,b,c,d ,e這5件寶物(不是5種寶物),它們的重量分別是2,2,6,5,4,它們的價值分別是6,3,5,4,6,現在給你個承重為10的背包, 怎么裝背包,可以才能帶走最多的財富。
此時只要理解了狀態轉換方程f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] },就知道這道算法的答案了,這個狀態轉換方程是怎么來的呢?往下看
假如背包要放第i件物品,此時如果不放第i件物品,那么問題就轉化為“前i-1件物品放入重量是w的背包中”,價值為f[i-1,j];
如果放第i件物品,那么問題就轉化為“前i-1件物品放入剩下的重量為j-Wi的背包中”,此時能獲得的最大價值就是f[i-1,j-Wi]
再加上通過放入第i件物品獲得的價值Pi,此時只要比較f[i-1,j]和f[i-1,j-Wi]+Pi那個大就能獲取到背包里最大的價值是多少了。
可能還是不是太懂,那么我們看圖來理解,這里就使用大佬的圖片了,就是下面的圖片,有編號分別為a,b,c,d,e的五件物品,它們的重量分別是2,2,6,5,4,它們的價值分別是6,3,5,4,6,現在給你個承重為10的背包,怎么獲取價值最大的背包呢
首先對這個圖片要知道的是:
- 明確這張表是至底向上,從左到右生成的。
- 然后用e2單元格表示e行2列的單元格,這個單元格的意義是用來表示只有物品e時,有個承重為2的背包,那么這個背包的最大價值是0,因為e物品的重量是4,背包裝不了。
- 對於d2單元格,表示只有物品e,d時,承重為2的背包,所能裝入的最大價值,仍然是0,因為物品e,d都不是這個背包能裝的。
- 同理,c2=0,b2=3,a2=6。
對於承重為8的背包,a8=15,是怎么得出的呢?根據01背包的狀態轉換方程,需要考察兩個值,就是下面的兩個
-
一個是f[i-1,j],這種情況就是承重為8的背包里面不放a這個物品這一種情況(根據上面的狀態轉換方程來的),這里i就是下面的橫列的值,然后j就是指豎列的值,所以此時f[i-1,j]里面的i就是a、j就是8,因為a的下一列是b,所以f[i-1,j]就是指b8,所以此時的f[i-1,j]的值就是9
-
另一個是f[i-1,j-Wi]+Pi,這種情況就是承重為8的背包里面要放a這個物品這一種情況(根據上面的狀態轉換方程來的),既然要放a這個物品,那么此時的Pi的值就是6(因為a商品的價值是6),然后因為承重為8的背包里面已經確定要放a這個物品,所以此時這個背包里面最多還只能存放的重量就是6,這里i就是下面的橫列的值,然后j就是指豎列的值,所以此時f[i-1,j-Wi]里面的i就是a、j就是8、Wi就是2(這個2就是a物品的重量),所以此時f[i-1,j-Wi]就是指b6,此時b6的值是9,所以f[i-1,j-Wi]+Pi=9+6=15,所以物品a應該放入稱重是8的背包里面
java代碼解答這個背包問題
下面的紅色代碼注釋里面的數組里面的第一個索引都是0,這是為了避免數組的0索引問題
下面的藍色代碼注釋里面的for循環目的就是為了創建 這樣的一個圖片,然后只要創建好上面的圖片,那么我們就能知道背包問題的答案了
package com.one.util;
public class Test {
public static int getMaxValue(int[] weight, int[] value, int w, int n) {
int[][] table = new int[n + 1][w + 1];// 創建一個二維數組,橫列是物品的價值,豎列是物品的重量
// 藍色代碼注釋開始
for (int i = 1; i <= n; i++) { //物品
for (int j = 1; j <= w; j++) { //背包大小
if (weight[i] > j) {
//當前物品i的重量比背包容量j大,裝不下,肯定就是不裝
table[i][j] = table[i - 1][j];
} else { //裝得下,Max{裝物品i, 不裝物品i}
table[i][j] = Math.max(table[i - 1][j], table[i - 1][j - weight[i]] + value[i]);
}
}
}
// 藍色代碼注釋結束
return table[n][w];
}
public static void main(String[] args) {
int n = 5, w = 10; //物品個數,背包容量
// 紅色代碼注釋開始
int[] value = {0,6, 3, 5, 4, 6}; //各個物品的價值
int[] weight = {0,2, 2, 6, 5, 4}; //各個物品的重量
// 紅色代碼注釋結束
System.out.println(getMaxValue(weight, value, w, n));
}
}
大佬網址
https://blog.csdn.net/evillist/article/details/74455044
https://www.kancloud.cn/kancloud/pack/70125
https://blog.csdn.net/mu399/article/details/7722810