There are n
items and a backpack with size m
. Given array A
representing the size of each item and array V
representing the value of each item.
What's the maximum value can you put into the backpack?
Example
Example 1:
Input: m = 10, A = [2, 3, 5, 7], V = [1, 5, 2, 4]
Output: 9
Explanation: Put A[1] and A[3] into backpack, getting the maximum value V[1] + V[3] = 9
Example 2:
Input: m = 10, A = [2, 3, 8], V = [2, 5, 8]
Output: 10
Explanation: Put A[0] and A[2] into backpack, getting the maximum value V[0] + V[2] = 10
Challenge
O(nm) memory is acceptable, can you do it in O(m) memory?
Notice
A[i], V[i], n, m
are all integers.- You can not split an item.
- The sum size of the items you want to put into backpack can not exceed
m
. - Each item can only be picked up once
思路: 跟背包I类似,f[i][j]表示前i个物品组成重量为j的pack的总value是多少;我们还是从A[i-1] 能否进入pack来考虑
f[i][j] = Max( f[i-1][j] (不进去), (进去)f[i-1][j - A[i-1]] + V[i-1] ,前提条件是: j -A[i-1] >=0 && f[i-1][j- A[i-1]] != -1;
这里我们巧妙的运用了所有物品是大于0,这个属性去掉了一个数组,这个数组用来表示能够组成j的package,跟背包I里面的数组是一个数组。我们这里用-1来表示,能否组成j; O(N*M) 空间由于状态转移方程只能i-1有关,可以优化成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) {
int n = A.length;
int[][] f = new int[n + 1][m + 1];
for(int j = 0; j <= m; j++) {
f[0][j] = -1;
}
f[0][0] = 0;
for(int i = 1; i <= n; i++) {
for(int w = 0; w <= m; w++) {
f[i][w] = f[i - 1][w];
if(w >= A[i - 1] && f[i - 1][w - A[i - 1]] != -1) {
f[i][w] = Math.max(f[i][w], f[i - 1][w - A[i - 1]] + V[i - 1]);
}
}
}
int res = 0;
for(int w = 0; w <= m; w++) {
if(f[n][w] != -1) {
res = Math.max(res, f[n][w]);
}
}
return res;
}
}
空间优化,滚动数组:
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) {
int n = A.length;
int[][] f = new int[2][m + 1];
for(int j = 0; j <= m; j++) {
f[0][j] = -1;
}
f[0][0] = 0;
for(int i = 1; i <= n; i++) {
for(int w = 0; w <= m; w++) {
f[i % 2][w] = f[(i - 1) % 2][w];
if(w >= A[i - 1] && f[(i - 1) % 2][w - A[i - 1]] != -1) {
f[i % 2][w] = Math.max(f[i % 2][w], f[(i - 1) % 2][w - A[i - 1]] + V[i - 1]);
}
}
}
int res = 0;
for(int w = 0; w <= m; w++) {
if(f[n % 2][w] != -1) {
res = Math.max(res, f[n % 2][w]);
}
}
return res;
}
}