揹包問題學習筆記

01揹包

01揹包的概念

有N件物品和一個容量爲V的揹包。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使價值總和最大。
從這個題目中能夠看出,01揹包的特色就是:每種物品僅有一件,能夠選擇放或不放。html

狀態轉移方程

01揹包問題的狀態轉移方程是:算法

f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

其中,即fi表示前i件物品恰放入一個容量爲v的揹包能夠得到的最大價值。
上述方程右邊能夠理解爲兩種狀況,取最優值.
狀況一:第i件不放進去,這時所得價值爲:fi-1;
狀況二:第i件放進去,這時所得價值爲:fi-1]+w[i];編程

狀況二的意思是,若是第i件放進去,那麼在容量V-c[i]裏就要放進前i-1件物品.(引用自)數組

案例解析

有編號分別爲a,b,c,d,e的五件物品,它們的重量分別是2,2,6,5,4,它們的價值分別是6,3,5,4,6,如今給你個承重爲10的揹包,如何讓揹包裏裝入的物品具備最大的價值總和?spa

圖片描述
首先要明確這張表是至底向上,從左到右生成的.
只要你能經過找規律手工填寫出上面這張表就算理解了01揹包的動態規劃算法。
爲了敘述方便,用e2單元格表示e行2列的單元格,這個單元格的意義是用來表示只有物品e時,有個承重爲2的揹包,那麼這個揹包的最大價值是0,由於e物品的重量是4,揹包裝不了
對於d2單元格,表示只有物品e,d時,承重爲2的揹包,所能裝入的最大價值,仍然是0,由於物品e,d都不是這個揹包能裝的。(引用自)code

編程實現

var n = 5; //物品數量,該參數能夠自行設定
var v = 10; //揹包體積,該參數可自行設定
var volumArray = [4, 3, 5, 2, 5];//物品體積組成的數組,該參數可自行設定
var valueArray = [9, 6, 1, 4, 1];//物品價值組成的數組,該參數可自行設定
var tempArray = [];

for (let a = 0; a < n; a++) {
    tempArray[a] = [];
    for (let b = 0; b < v; b++) {
        tempArray[a].push(0);
    }
}

for (let i = 0; i < n; i++) {
    for (let j = 0; j < v; j++) {
        tempArray[i][j] = i == 0 ? 0 : tempArray[i - 1][j];
        if (i > 0 && j >= volumArray[i - 1]) {
            tempArray[i][j] = tempArray[i][j] >= tempArray[i - 1][j - volumArray[i - 1]] + valueArray[i - 1] ? tempArray[i][j] : tempArray[i - 1][j - volumArray[i - 1]] + valueArray[i - 1];
        }
    }
}

console.log(tempArray[n - 1][v - 1]);

徹底揹包

徹底揹包的概念

有N種物品和一個容量爲V的揹包,每種物品都有無限件可用。
第i種物品的體積是c,價值是w。求解將哪些物品裝入揹包可以使這些物品的體積總和不超過揹包容量,且價值總和最大。htm

狀態轉移方程

參考上述01揹包的轉移方程,不可貴出:blog

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}

僞代碼實現以下:圖片

for i=1...N
    for v=0...V
        for k=1...v/w[i]
            f[i][v] = max{f[i-1][v],f[i-1][v-k*w[i]]+k*c[i]};

案例解析

給你六種面額1,5,10,20,50,100元的紙幣,假設每種幣值的數量都足夠多,編寫程序求組成N元的不一樣組合個數.get

function fn (all) {
    const arr = [1, 5, 10, 20, 50, 100],
        len = arr.length,
        res = [];
    for (let i = 0; i <= len; i++) {
        res[i] = [];
        res[i][0] = 1;
    }
    for (let j = 1; j <= all; j++) {
        res[0][j] = 0;
    }
    for (let i = 1; i <= len; i++) {
        for (let j = 1; j <= all; j++) {
            res[i][j] = 0;
            for (let k = 0; k <= j / arr[i - 1]; k++) {
                res[i][j] += res[i - 1][j - k * arr[i - 1]];
            }
        }
    }
    return res[len][all];
}
相關文章
相關標籤/搜索