揹包問題之0-1揹包問題

問題描述:有n個物品,第 i 個物品的重量與價值分別爲 w[i]w[i]v[i]v[i]。揹包容量爲 V,試問在每個物品最多使用一次(物品必須保持完整)的情況下,如何讓揹包裝入的物品具有更大的價值總和。現有數據如下:

w = [2,3,4,5];
v = [3,4,5,6];
V = 8;

解題思路:令 dp[i][j]dp[i][j] 表示容量爲 j 時放入前 i 個物品的最大價值。對於第 i 件物品,有兩種選擇,即放或者不放。若不放,則 dp[i][j]=dp[i1][j]dp[i][j]=dp[i-1][j];如放,則 dp[i][j]=dp[i1][jw[i]]+v[i]dp[i][j]=dp[i-1][j-w[i]]+v[i]。因此有 dp[i][j]=max(dp[i1][j],dp[i1][jw[i]]+v[i])dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

    public int knapsackProblem(int[] w, int[] v, int cap) {
        int[][] dp = new int[w.length + 1][cap + 1];
        for (int i = 1; i <= w.length; i++) {
            for (int j = cap; j >= 1; j--) {
                if (w[i - 1] <= j) {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[w.length][cap];
    }

時間複雜度與空間複雜度均爲 O(nV)O(nV)

空間優化:由以上可知,迭代過程中的第 i 行僅與前一行相關,因此可以將存儲空間可被壓縮成一維數組,即 dp[j]=max{dp[j],dp[jw[i]]+v[i]}dp[j]=max\{dp[j],dp[j-w[i]]+v[i]\}。由於 dp[jw[i]]dp[j-w[i]] 表示的是上一行容量小於 j 的值,爲了避免數據被覆蓋,需從後往前進行計算。

    public int knapsackProblem(int[] w, int[] v, int cap) {
        int[] dp = new int[cap + 1];
        for (int i = 0; i < w.length; i++) {
            for (int j = cap; j >= w[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);
            }
        }
        return dp[cap];
    }

上一篇:揹包問題之分數揹包問題
下一篇:揹包問題之完全揹包問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章