動態規劃之01揹包問題(最易理解的講解)
轉載地址:http://blog.csdn.net/mu399/article/details/7722810
01揹包問題,是用來介紹動態規劃演算法最經典的例子,網上關於01揹包問題的講解也很多,我寫這篇文章力爭做到用最簡單的方式,最少的公式把01揹包問題講解透徹。
01揹包的狀態轉換方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }
題目描述:
有編號分別為a,b,c,d,e的五件物品,它們的重量分別是2,2,6,5,4,它們的價值分別是6,3,5,4,6,現在給你個承重為10的揹包,如何讓揹包裡裝入的物品具有最大的價值總和?
name | weight | value | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
a | 2 | 6 | 0 | 6 | 6 | 9 | 9 | 12 | 12 | 15 | 15 | 15 |
b | 2 | 3 | 0 | 3 | 3 | 6 | 6 | 9 | 9 | 9 | 10 | 11 |
c | 6 | 5 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 10 | 11 |
d | 5 | 4 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 10 | 10 |
e | 4 | 6 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
只要你能通過找規律手工填寫出上面這張表就算理解了01揹包的動態規劃演算法。
首先要明確這張表是至底向上,從左到右生成的。
為了敘述方便,用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],對於這個例子來說就是b8的值9,另一個是f[i-1,j-Wi]+Pi;
在這裡,
f[i-1,j]表示我有一個承重為8的揹包,當只有物品b,c,d,e四件可選時,這個揹包能裝入的最大價值
f[i-1,j-Wi]表示我有一個承重為6的揹包(等於當前揹包承重減去物品a的重量),當只有物品b,c,d,e四件可選時,這個揹包能裝入的最大價值
f[i-1,j-Wi]就是指單元格b6,值為9,Pi指的是a物品的價值,即6
由於f[i-1,j-Wi]+Pi = 9 + 6 = 15 大於f[i-1,j] = 9,所以物品a應該放入承重為8的揹包
以下是java的程式碼view plain copy
import java.util.Arrays;
public class Package01 {
public static void main(String[] args) {
int wholeWeight = 10;
PackageItem[] packageItems = init();
int[][] result = get01PackageAnswer(packageItems, wholeWeight);
for (int i = 0; i < result.length; i++) {
System.out.println(Arrays.toString(result[i]));
}
}
private static int[][] get01PackageAnswer(PackageItem[] packageItems, int wholeWeight) {
int[][] matrix = new int[packageItems.length][wholeWeight + 1];//二位陣列
for (int i = 0; i < packageItems.length; i++) {//行
PackageItem pi = packageItems[i];//要放進包的item
int piWeight = pi.weight;
int piValue = pi.value;
for (int j = 1; j <= wholeWeight; j++) {//列
int bagSize = j;//當前揹包的能承受的重量
if (piWeight > bagSize) {//裝不了
//matrix[i][j] = matrix[i][j - 1];
if (i ==0) {//如果是第0行
matrix[i][j] = 0;
} else {
matrix[i][j] = matrix[i - 1][j];
}
} else {
int weightDiff = bagSize - piWeight;//裝入當前item,餘下的重量
if (i ==0) {//如果是第0行
matrix[i][j] = piValue;
} else {
int valueInBag = matrix[i - 1][weightDiff] + piValue;//f[i-1,j-Wi]+Pi(j >= Wi)
matrix[i][j] = valueInBag > matrix[i - 1][j] ? valueInBag : matrix[i - 1][j];
}
}
}
}
return matrix;
}
static PackageItem[] init() {
String[] nameArr = {"a","b","c","d","e"};
int[] weightArr = {2,2,6,5,4};
int[] valueArr = {6,3,5,4,6};
PackageItem[] packageItems = new PackageItem[nameArr.length];
for (int i = 0; i < nameArr.length; i++) {
PackageItem pi = new PackageItem(nameArr[i], weightArr[i], valueArr[i]);
packageItems[i] = pi;
}
return packageItems;
}
}
class PackageItem
{
public String name;
public int weight;
public int value;
public PackageItem(String name, int weight, int value)
{
this.name = name;
this.weight = weight;
this.value = value;
}
}
相關文章
- 動態規劃 01揹包問題動態規劃
- 【動態規劃】01揹包問題動態規劃
- 動態規劃-01揹包問題動態規劃
- 動態規劃--01揹包問題動態規劃
- 01揹包問題理解動態規劃演算法動態規劃演算法
- 動態規劃系列之六01揹包問題動態規劃
- 【動態規劃】01揹包問題【續】動態規劃
- 揹包問題----動態規劃動態規劃
- 【動態規劃】揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 動態規劃之 0-1 揹包問題詳解動態規劃
- 詳解動態規劃01揹包問題--JavaScript實現動態規劃JavaScript
- 詳解動態規劃01揹包問題–JavaScript實現動態規劃JavaScript
- 動態規劃之0,1揹包問題動態規劃
- 動態規劃解0-1揹包問題動態規劃
- 動態規劃-揹包01問題推理與實踐動態規劃
- 雙核處理(動態規劃的01揹包問題)動態規劃
- 0-1揹包問題(動態規劃)動態規劃
- python 動態規劃(揹包問題和最長公共子串)Python動態規劃
- 0-1揹包問題 動態規劃法動態規劃
- 動態規劃-揹包類動態規劃
- 01揹包動態規劃空間優化動態規劃優化
- 【動態規劃】一次搞定三種揹包問題動態規劃
- 前端與演算法-動態規劃之01揹包問題淺析與實現前端演算法動態規劃
- 【動態規劃】0-1揹包問題原理和實現動態規劃
- 動態規劃0-1揹包動態規劃
- 演算法-動態規劃-完全揹包演算法動態規劃
- 01揹包問題的解決
- 揹包問題(01揹包與完全揹包)
- 揹包問題演算法全解析:動態規劃和貪心演算法詳解演算法動態規劃
- 洛谷 1064——金明的預算方案(動態規劃的揹包問題)動態規劃
- 多重揹包動態規劃及空間優化動態規劃優化
- 01揹包問題
- 【LeetCode動態規劃#06】分割等和子集(01揹包問題一維寫法實戰)LeetCode動態規劃
- 以最長公共子序列問題理解動態規劃演算法(DP)動態規劃演算法
- 【LeetCode動態規劃#05】揹包問題的理論分析(基於程式碼隨想錄的個人理解,多圖)LeetCode動態規劃
- 動態規劃求解最長上升子序列問題動態規劃
- 最長公共子序列問題—動態規劃sdut動態規劃