该题是lintcode上的125 · 背包问题(二)算法题,该题的解题思路是按照九章侯老师给的方法去实现的。
有 n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.
问最多能装入背包的总价值是多大?
1. A[i],V[i],n,m均为整数
2. 您不能将物品进行切分
3. 您所挑选的要装入背包的物品的总大小不能超过m
4. 每个物品只能取一次
5. m <= 100,即len(a) 和len(v) <= 100
输入:
m = 10
A = [2, 3, 5, 7]
V = [1, 5, 2, 4]
输出:
9
解释:
装入 A[1] 和 A[3] 可以得到最大价值, V[1] + V[3] = 9
输入:
m = 10
A = [2, 3, 8]
V = [2, 5, 8]
输出:
10
解释:
装入 A[0] 和 A[2] 可以得到最大价值, V[0] + V[2] = 10
O(nm) 空间复杂度可以通过, 你能把空间复杂度优化为O(m)吗?
该问题主要是要知道N个物品是否可以拼出重量M,对于每个重量M,最大总价值为多少。
最后一步:最后一个物品是否需要放入背包中
选择1:如果前N - 1个物品就可以拼出重量M,最大价值为V,那么前N个物品也能拼出M且总价值为M。
选择2:如果前N - 1个物品能拼出M - An-1,最大总价值为V,则再加上最后一个物品(重An-1,价值为Vn-1),能拼出M,总价值为:V + Vn-1
设:f[i][]j表示用前i个物品拼出重量为j时的最大总价值(-1表示不能拼出j)
初始化f[0][0], f[0][1], …, f[0][M]
计算前1个物品可以拼出各种重量的最大总价值:f[1][0], f[1][1], …, f[1][M]
…
计算前N个物品拼出各种重量的最大价值:f[N][0], f[N][2], …, f[N][M]
最后结果为:max0<=j<=M{f[N][j] | f[N][j] ≠-1}
时间复杂度为:O(MN)
空间复杂度为:O(MN)
空间优化后的复杂度为:O(M)
public class Solution {
/**
* @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
*/
public int backPackII(int m, int[] a, int[] v) {
// write your code here
int n = a.length;
int [][] f = new int[n + 1][m + 1];
f[0][0] = 0;
for (int i = 1; i <= m; i++) {
f[0][i] = -1;
}
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]] != -1) {
f[i][j] = Math.max(f[i][j], f[i - 1][j - a[i - 1]] + v[i - 1]);
}
}
}
int res = 0;
for (int i = 0; i <= m; i++) {
if (f[n][i] != -1) {
res = Math.max(res, f[n][i]);
}
}
return res;
}
}
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();
vector<vector<int>> f(n + 1, vector<int>(m + 1, -1));
f[0][0] = 0;
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]] != -1)) {
f[i][j] = max(f[i][j], f[i - 1][j - a[i - 1]] + v[i - 1]);
}
}
}
int res = 0;
for (int i = 0; i <= m; i++) {
if (f[n][i] != -1) {
res = max(res, f[n][i]);
}
}
return res;
}
};
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();
vector<int> f(m + 1, 0);
for (int i = 1; i <= n; i++) {
for (int j = m; j >= a[i - 1]; j--) {
f[j] = max(f[j], f[j - a[i - 1]] + v[i - 1]);
}
}
return f[m];
}
};