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.
Challenge
O(n x m) time and O(m) memory.
O(n x m) memory is also acceptable if you do not know how to optimize memory.
Tags
LintCode Copyright Dynamic Programming Backpack
Related Problems
Medium Backpack VI 30 %
Medium Backpack V 38 %
Medium Backpack IV 36 %
Hard Backpack III 50 %
Medium Backpack II 37 %
Analysis
背包问题序列I
要点: 单次选择+最大体积
常用是DP,但也可以用递归+记忆化搜索来做。
这个问题没有给每个物品的价值,也没有问最多能获得多少价值,而是问最多能装多满。
实际上在这里,如果我们把每个物品的大小当作每个物品的价值,就可以完美解决这个问题。
Solution
Preferred Solution
2D - DP
状态:
dp[i][j] - 代表在前 i 件物品中选择若干件,这若干件物品的体积和不超过 j 的情况下,所能获得的最大容量
publicclassSolution {publicintbackPack(int m,int[] A) {int[] dp =newint[m+1];for (int i =0; i <A.length; i++) {for (int j = m; j >0; j--) {if (j >=A[i]) { dp[j] =Math.max(dp[j], dp[j -A[i]] +A[i]); } } }return dp[m]; }}
1D DP
j = m, m-1, ..., A[i]
publicintbackPack(int m,int[] A) {int[] dp =newint[m +1];for (int i =0; i <A.length; i++) {for (int j = m; j >=A[i]; j--) { dp[j] =Math.max(dp[j], dp[j -A[i]] +A[i]); } }return dp[m]; }
Another DP Approach (NOT Preferred)
2D with O(n * m) time and O(n * m) space.
动态规划4要素
State:
f[i][S] “前i”个物品,取出一些能否组成和为S
Function:
f[i][S] = f[i-1][S - a[i]] or f[i-1][S]
Initialize:
f[i][0] = true; f[0][1..target] = false
Answer:
检查所有的f[n][j]
O(n * S) , 滚动数组优化
注意这里A[i - 1]的数组下标,因为新建的是i = 1, ..., A.length
publicclassSolution { /** * @param m: An integer m denotes the size of a backpack * @param A: Given n items with size A[i] * @return: The maximum size */publicintbackPack(int m,int[] A) {boolean[][] dp =newboolean[A.length+1][m +1]; dp[0][0] =true;for (int i =1; i <=A.length; i++) {for (int j =0; j <= m; j++) { dp[i][j] = dp[i -1][j] || (j -A[i -1] >=0&& dp[i -1][j -A[i -1]]); } }for (int j = m; j >=0; j--) {if (dp[A.length][j]) {return j; } }return0; }}
1D version with O(n * m) time and O(m) memory.
publicclassSolution { /** * @param m: An integer m denotes the size of a backpack * @param A: Given n items with size A[i] * @return: The maximum size */publicintbackPack(int m,int[] A) {if (A.length==0) return0;int n =A.length;boolean[] dp =newboolean[m +1];Arrays.fill(dp,false); dp[0] =true;for (int i =1; i <= n; i++) {for (int j = m; j >=0; j--) {if (j -A[i -1] >=0&& dp[j -A[i -1]]) { dp[j] = dp[j -A[i -1]]; } } }for (int i = m; i >=0;i--) {if (dp[i]) return i; }return0; }}
int max =Integer.MAX_VALUE;publicintbackPack(int m,int[] A) {Arrays.sort(A);boolean[] visited =newboolean[m +1];int[] memo =newint[m +1];dfs( m , A ,0,visited , memo );return m - max ; }privateintdfs( int target ,int[] A ,int startIndex ,boolean[] visited ,int[] memo){if(visited[target]){return memo[target]; }int res = target;for(int i = startIndex ; i <A.length ; i++){if(target -A[i] >=0){ res =dfs( target -A[i] , A , i +1,visited ,memo); }else{break; } } visited[target] =true; memo[target] = res; max =Math.min(max ,res);return res; }