题目地址:
http://www.lintcode.com/problem/backpack-ii/description
0-1背包问题, 表示物品体积, 表示物品价值。用动态规划。设 是前 个物品里取出若干总重量不超过 的物品的价值最大值。这个最大值有两种可能,要么包含物品 ,此时最大值是 ;要么不包含物品 ,此时最大值是 。比较一下这两个最大值取大者,就是 。从上面的式子看出,更新顺序是, 从小到大, 也是从小到大。代码如下:
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[][] f = new int[A.length][m + 1];
for (int i = 0; i <= m; i++) {
f[0][i] = A[0] <= i ? V[0] : 0;
}
for (int i = 1; i < A.length; i++) {
for (int j = 0; j <= m; j++) {
f[i][j] = f[i - 1][j];
if (j >= A[i]) {
f[i][j] = Math.max(f[i][j], f[i - 1][j - A[i]] + V[i]);
}
}
}
return f[A.length - 1][m];
}
}
时空复杂度 , 是物品数量。
接下来考虑优化空间复杂度。可以看到, 的值只取决于上一行正上方元素和上一行左边的元素,所以可以按行滚动做空间优化。每一行需要从右向左更新,否则的话更新到 的时候, 已经被覆盖掉了,这个时候答案已经得不到了。具体代码如下:
import java.util.Arrays;
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[] f = new int[m + 1];
for (int i = 1; i <= m; i++) {
f[i] = A[0] <= i ? V[0] : 0;
}
// f[j] The max value of taking the first i items with total volume <= m
for (int i = 1; i < A.length; i++) {
for (int j = m; j >= 0; j--) {
if (j >= A[i]) {
f[j] = Math.max(f[j], f[j - A[i]] + V[i]);
}
}
}
return f[m];
}
}
时间复杂度不变,空间 。