九章算法 - 五、揹包型動態規劃 92. 563. 564. 125. 440.

關鍵點:最後一個揹包的內的物品是哪個,最後一個物品有沒有進揹包。

             揹包問題要將總承重放入狀態。

可行性揹包,計數型揹包,最值型揹包。

92. Backpack

在n個物品中挑選若干物品裝入揹包,最多能裝多滿?假設揹包的大小爲m,每個物品的大小爲A[i]

提示: 兩種思路,第一種狀態是f[i][w]表示能否用前i個物品拼出重量w。優化空間的的話,可以不在f中記錄i,然後從後向前遍歷              輸出第一個爲true的w的值。

           第二種思路是直接記錄重量。

答案:

第一種

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    int backPack(int m, vector<int> A) {
        int n = A.size();
        vector<vector<bool>> f(n + 1, vector<bool>(m + 1, false));
        f[0][0] = true;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                f[i][j] = f[i - 1][j];
                if (j >= A[i-1] && f[i-1][j - A[i-1]]) {
                    f[i][j] = true;
                }
            } // for j
        } // for i
        
        for (int i = m; i >= 0; i--) {
            if (f[n][i]) {
                return i;
            }
        }
        
        return 0;
      
    }
};
class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    int backPack(int m, vector<int> A) {
        vector<bool> f(m + 1, false);
        f[0] = true;
       
        for (int i = 0; i < A.size(); i++) {
            for (int j = m; j >= A[i]; j--) {
                f[j] = f[j] || f[j - A[i]];
            } 
        } 
        for (int j = m; j >= 0; j--) {
            if (f[j]) {
                return j;
            }
        }
        return 0;
    }
};

第二種

public class Solution {
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    public int backPack(int m, int[] A) {
        // write your code here
        int f[] = new int[m + 1];

        for (int i = 0; i < A.length; i++) {
            for (int j = m; j >= A[i]; j--) {
                f[j] = Math.max(f[j], f[j - A[i]] + A[i]);
            } 
        }
        return f[m];
    }
}

563. Backpack V

給定N個正整數數組: A0, A1, ... , A n-1

一個正整數Target,求多少種組合加起來是Target,每個Ai只能用一次

提示:

答案:

public class Solution {
    int backpackV(vector<int> A, int T){
         int i, j;
         int n = A.size();
         if(n == 0) return 0;
        
        vector<int> f(T + 1, 0);
        f[0] = 1;
        
        for(i = 1; i <= n; i++){
            for(j = T; j >= 0; j--){
                if(j >= A[i]){
                    f[j] = f[j - A[i]];
                }
            } 
        }
        return f[T];
    }
}

564. Backpack VI

給出一個都是正整數的數組 nums,其中沒有重複的數。從中找出所有的和爲 target 的組合個數。一個數可以在組合中出現多次。數的順序不同則會被認爲是不同的組合。

提示:

答案:

class Solution {
public:
    /**
     * @param nums an integer array and all positive numbers, no duplicates
     * @param target an integer
     * @return an integer
     */
    int backPackVI(vector<int>& nums, int target) {
        // Write your code here
        vector<int> dp(target + 1);
        dp[0] = 1;
        for (int i = 1; i <= target; ++i) {
            for (auto a : nums)
            if (i >= a) {
                dp[i] += dp[i - a];
            }
        }
        return dp.back();
    }
};

125. Backpack II

有 n 個物品和一個大小爲 m 的揹包. 給定數組 A 表示每個物品的大小和數組 V 表示每個物品的價值.

問最多能裝入揹包的總價值是多大?

提示:

答案:

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A & V: Given n items with size A[i] and value V[i]
     */
    int backPackII(int m, vector<int> A, vector<int> V) {
        // write your code here
        int f[m + 1];
        for (int i = 0; i <=m ; ++i) f[i] = 0;
        int n = A.size() , i, j;
        for(i = 0; i < n; i++){
            for(j = m; j >= A[i]; j--){
                f[j] = max(f[j], f[j - A[i]] + V[i]);
            }
        }
        return f[m];
    }
};

440. Backpack III

給定N種物品,重量爲A[i],價值爲V[i],每種物品有無窮多個,揹包最大承重是正整數M,求能帶走的物品的最大價值。

提示:

優化之後將時間複雜度從O(M^2N)減少到O(MN),之後發現從左向右計算正好可以利用前面計算的新值與同列的老值,優化空間到O(N)。想對於揹包II只需改一行代碼,把從後往前改爲從前往後,這是一個巧合。

答案:

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A & V: Given n items with size A[i] and value V[i]
     */
    int backPackIII(int m, vector<int> A, vector<int> V) {
        // write your code here
        int f[m + 1];
        for (int i = 0; i <=m ; ++i) f[i] = 0;
        int n = A.size() , i, j;
        for(i = 0; i < n; i++){
            for(j = A[i]; j <= m; j++){
                f[j] = max(f[j], f[j - A[i]] + V[i]);
            }
        }
        return f[m];
    }
};

 

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