版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/roufoo/article/details/83048236
本文参考了九章的背包教程:
解法1:
经典DP解法。
时间复杂度O(MN),空间复杂度O(MN)。
注意:dp[m+1][n+1],如果定义成dp[m][n],dp[0][]就有歧义:到底表示不取任何包,还是取包0呢?
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) {
int itemCount = A.size();
//dp[itemCount][packSize]
vector<vector<int>> dp(itemCount + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= itemCount; ++i) {
for (int j = 0; j <= m; ++j) {
dp[i][j] = dp[i - 1][j];
if (j >= A[i - 1]) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - A[i - 1]] + V[i - 1]);
}
}
}
return dp[itemCount][m];
}
};
解法2:
在解法1的基础上加上滚动数组优化:
时间复杂度O(MN)
空间复杂度O(N)
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) {
int itemCount = A.size();
//dp[2][packSize]
vector<vector<int>> dp(2, vector<int>(m + 1, 0));
int rotate = 0;
for (int i = 0; i <= itemCount; ++i) {
rotate ^= 1;
for (int j = 0; j <= m; ++j) {
dp[rotate][j] = dp[rotate ^ 1][j];
if (j >= A[i - 1]) {
dp[rotate][j] = max(dp[rotate][j], dp[rotate ^ 1][j - A[i - 1]] + V[i - 1]);
}
}
}
return dp[rotate][m];
}
};
解法3:
将第2层循环倒序,因为i时候的dp[j - A[i - 1]]实际上就是i-1时候的dp[j - A[i - 1]],因为倒序的时候,dp[j]更新了,此时dp[j - A[i - 1]]还未更新。
时间复杂度还是O(MN)。
空间复杂度还是O(N)。但只用了一个一维数组。
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) {
int itemCount = A.size();
//dp[packSize]
vector<int> dp(m + 1, 0);
for (int i = 1; i <= itemCount; ++i) {
for (int j = m; j >= A[i - 1]; --j) {
dp[j] = max(dp[j], dp[j - A[i - 1]] + V[i - 1]);
}
}
return dp[m];
}
};