Lintcode 92. 背包问题 && 125. 背包问题 II

92. 背包问题

描述

在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]

你不可以将物品进行切割。

样例

如果有4个物品[2, 3, 5, 7]

如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。

如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。

函数需要返回最多能装满的空间大小。

挑战

O(n x m) time and O(m) memory.

O(n x m) memory is also acceptable if you do not know how to optimize memory.

思路:背包问题的经典题目,之前看过一点背包问题九讲,想详细了解的可以去看看,对动态规划会有更深的了解。

本题的思路就是一个递推关系:DP[i][s] = max(DP[i-1][s],DP[i-1][s-A[i]]+A[i])。DP[i][s]表示前i种物品填充s大小的背包所能得到的最大空间。递推关系的意思就是第i件物品放入(此时所剩空间当然只剩s-A[i])和不放入两种情况取较大值。

只要理解了这个动态规划的两个变化维度写代码就容易了。下面是我写的没经过空间优化的版本:

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) {
        // write your code here
        int size = A.size();
        vector<vector<int>> DP(size + 1,vector<int>(m + 1,0));
        for(int i = 1; i <= size; ++i){
            for(int s = 1; s <= m; ++s){
                DP[i][s] = s-A[i-1] >= 0? max(DP[i-1][s],DP[i-1][s-A[i-1]] + A[i-1]) :DP[i-1][s];//防止越界判断
            }
        }
        return DP[size][m];
    }
};

使用滑动数组可以优化空间,具体思路可以见上面的背包问题九讲,代码:

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(), i = 0, j = 0;
        vector<int> dp(m + 1, 0);
        for(i=0; i<n; i++) {
            for(j=m; j>=1; j--) {
                if(j >= A[i]) {
                    dp[j] = max(dp[j],dp[j-A[i]] + A[i]);//根据递推关系可知每一轮变化从后往前进行
                }
            }
        }
        return dp[m];
    }
};

125. 背包问题 II

描述

给出n个物品的体积A[i]和其价值V[i],将他们装入一个大小为m的背包,最多能装入的总价值有多大?

A[i], V[i], n, m均为整数。你不能将物品进行切分。你所挑选的物品总体积需要小于等于给定的m。

样例

对于物品体积[2, 3, 5, 7]和对应的价值[1, 5, 2, 4], 假设背包大小为10的话,最大能够装入的价值为9。

挑战

O(n x m) memory is acceptable, can you do it in O(m) memory?

思路:和上面的题目思路完全相同,连代码都差不多,唯一需要变化的就是更新判断标准变成了总价值。

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @param V: Given n items with value V[i]
     * @return: The maximum value
     */
    int backPackII(int m, vector<int> &A, vector<int> &V) {
        // write your code here
        int n = A.size(), i = 0, j = 0;
        vector<int> dp(m + 1, 0);
        for(i=0; i<n; i++) {
            for(j=m; j>=1; j--) {
                if(j >= A[i]) {
                    dp[j] = max(dp[j],dp[j-A[i]] + V[i]);//只有这一行变化了
                }
            }
        }
        return dp[m];
    }
};

 

猜你喜欢

转载自www.cnblogs.com/J1ac/p/9093574.html