Java-揹包算法實現

介紹

給定 n 種物品和一個容量爲 C 的揹包,物品 i 的重量是 $w_i$,其價值爲 $v_i$
問:應該如何選擇裝入揹包的物品,使得裝入揹包中的物品的總價值最大?

揹包問題是具有許多應用的組合優化問題

揹包問題

在揹包問題中,我們有一組物品。每個物品都有重量和價值:

揹包算法示例.png

我們想將這些物品放入揹包。但是,它有一個重量限制:

未命名文件 (2).png

因此,我們需要選擇總重量不超過重量限制的物品,並且其總價值達到最高。 例如,上述示例的最佳解決方案是選擇5kg和6kg物品,它們在重量限制內的最大值爲40元

揹包問題有幾種變化,我們將重點介紹0-1揹包問題。在0-1揹包問題中,必須選擇每個物品或將其留在後面。我們不能取一部分物品。另外,我們不能多次取一件物品。

數學公式

現在讓我們以數學符號形式化0-1揹包問題。給定一組n個物品和重量限制W,我們可以將優化問題定義爲:

公式

**這個問題是NP完全難題
)。**因此,目前尚無多項式時間算法可以解決。但是,對於此問題,可以使用動態規劃算法思路來解決。

遞歸算法

使用遞歸公式來解決此問題:

遞歸算法

在該公式中,$M_(n,w)$ 是重量限制爲w的n個物品的最優解。它是以下兩個值中的最大值:

重量限制爲w的(n-1)個物品的最優解(不包括第n個項目)
第n個物品的值加上(n-1)個物品的最優解和w減去第n個物品的權重(包括第n個物品)
如果第n項的重量大於當前的重量限制,則不包括在內。因此,它屬於上述兩種情況的第一類。

Java中實現此遞歸公式代碼:

image.png

在每個遞歸步驟中,我們需要評估兩次最優解決邏輯,因此,此遞歸解決方案的運行時間爲O($2^n$)。

動態規劃算法

動態規劃思路是一種用於線性化,指數級遞增的編程算法的思路,這個思路是存儲子問題的結果,這樣我們以後就不必重新計算它們了。

我們還可以通過動態規劃解決0-1揹包問題。要使用動態規劃中,我們使用自下而上的方法來計算最佳解決方案:

/**
     * @param w : 已知物品重量數組集合
     * @param v  : 已知物品價值數組集合
     * @param n  : 最大價值,0 表示不要求
     * @param W : 最大重量,0 表示不要求
     * @author 油膩的Java
     * @date 2019/11/5
     * @return
     */
    public int knapsackDP(int[] w, int[] v, int n, int W) {
        if (n <= 0 || W <= 0) {
            return 0;
        }

        /**
         * 創建臨時數組
         */
        int[][] m = new int[n + 1][W + 1];
        for (int j = 0; j <= W; j++) {
            m[0][j] = 0;
        }

        /**
         * 遍歷n和W,
         */
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= W; j++) {
                if (w[i - 1] > j) {
                    //對m數組進行賦值
                    m[i][j] = m[i - 1][j];
                } else {
                    //求最大值
                    m[i][j] = Math.max(m[i - 1][j], m[i - 1][j - w[i - 1]] + v[i - 1]);
                }
            }
        }
        return m[n][W];
    }

在代碼中,我們在商品價值n和重量限制W上有一個嵌套循環。因此,它的運行時間爲O(nW)。

單元測試

最後針對各自的場景做了一下單元測試

同時滿足價格,重量最大化

image.png

最大重量最優解

image.png

最大價格最優解

image.png

結論

本文通過編寫遞歸算法、動態規劃算法來解決揹包0-1問題,以及測試相應的單元測試,希望在揹包算法對你有新的認知。

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