Given n items with size Ai, an integer m denotes the size of a backpack. How full you can fill this backpack?
Notice
You can not divide any item into small pieces.
Example
第二种算法使用二维动态规划。
If we have 4
items with size [2, 3, 5, 7]
, the backpack size is 11, we can select[2, 3, 5]
, so that the max size we can fill this backpack is 10
. If the backpack size is 12
. we can select [2, 3, 7]
so that we can fulfill the backpack.
You function should return the max size we can fill in the given backpack.
第一种算法,排序后遍历数组。结果超时。复杂度O(N×N)
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
Arrays.sort(A);
int[] res = new int[]{0};
get(m, A, 0, res, 0);
return res[0];
}
private void get(int m, int[] A, int curr, int[] max, int index) {
if(index >= A.length) return ;
for(int i = index; i < A.length; i++) {
if(A[i] > m - curr) return;
else {
if(max[0] <= curr + A[i] && curr + A[i] <= m) max[0] = curr + A[i];
get(m, A, curr + A[i], max, i + 1);
}
}
}
}
第二种算法使用二维动态规划。
res[i][j]代表有i个球时,最大空间为j的背包可以放的实际最大空间。
状态转移方程为:res[i][j] = max(res[i - 1][j - A[i]]+A[i], res[i - 1][j]);
即如果第i个物品可以放入背包,则先找到j-A[i]重量的背包的实际最大重量,然后加上第i个物品的重量。否则,实际最大重量不变。
优化可以考虑使用滚动数组
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
int length = A.length;
int[][] res = new int[length][m + 1];
for(int i = 0; i < length; i++) {
res[i][0] = 0;
}
for(int j = 1; j <= m; j++) {
if(A[0] <= j) res[0][j] = A[0];
else res[0][j] = 0;
for(int i = 1; i < length; i++) {
if(j >= A[i]) {
res[i][j] = Math.max(res[i - 1][j - A[i]] + A[i], res[i - 1][j]);
} else {
res[i][j] = res[i - 1][j];
}
}
}
return res[length - 1][m];
}
}