1. 程式人生 > >LintCode798: Backpack VII (完全揹包問題 DP經典)

LintCode798: Backpack VII (完全揹包問題 DP經典)

完全揹包問題可以視為01揹包的變形。

解法1:沒有經過優化的DP。 dp[i][j] 表示前i件物品在價值不超過j的情況下的最大重量。 若輸入為: 8 //n = money [3,2] //prices [300,160] //weight [1,6] //amounts 輸出為 640 dp[][] 為: 0 0 0 0 0 0 0 0 0 0 0 0 300 300 300 300 300 300 0 0 160 300 320 460 480 620 640 注意這裡不能用貪婪法。比如說先花3元買weight為300的物品,然後剩下5元買兩件weight為160的物品。這樣重量為620,非最優。原因是這樣會剩下1元用不上

時間複雜度O(nW): n是所有item的總和(注意每個item可能有若干個), W是總的money數。

class Solution {
public:
    /**
     * @param n: the money of you
     * @param prices: the price of rice[i]
     * @param weight: the weight of rice[i]
     * @param amounts: the amount of rice[i] 
     * @return: the maximum weight
     */
    int backPackVII(int n, vector<int> &prices, vector<int> &weight, vector<int> &amounts) {
        int itemCount = prices.size();   //count of items
        vector<vector<int>> dp(itemCount + 1, vector<int>(n + 1, 0)); //dp[i][j] means the maximum weight of first i tems with total price <= j
        
        for (int i = 1; i <= itemCount; ++i) { // i->item[i]
            for (int k = 1; k <=n; ++k) {
                dp[i][k] = dp[i - 1][k];
            }

            for (int j = 0; j <= amounts[i - 1]; ++j) { //j-> amount[0]..amount[i-1]
                for (int k = 1; k <= n; ++k) { //k->  1 .. n
                    if (k >= j * prices[i - 1]) {
                        dp[i][k] = max(dp[i][k], dp[i - 1][k - j * prices[i - 1]] + j * weight[i - 1]);
                    }
                }
            }
        }

        return dp[itemCount][n];
    }
};

另外還要注意,上面的三層迴圈不能這樣寫: 原因是dp[i][k]被 j 迴圈和 i 迴圈改寫了,而dp[i][k]應該是獨立於 j 迴圈的。

for (int i = 1; i <= itemCount; ++i) { // i->item[i]
            for (int j = 0; j <= amounts[i - 1]; ++j) { //j-> amount[0]..amount[i-1]
                for (int k = 1; k <= n; k++) { //k->  1 .. n
                    dp[i][k] = dp[i - 1][k];  //應該提出去
                    
                    if (k >= j * prices[i - 1]) {
                        dp[i][k] = max(dp[i][k], dp[i - 1][k - j * prices[i - 1]] + j * weight[i - 1]);
                    }
                }
            }
        }