标签:
Given n items with size Ai, an integer m denotes the size of a backpack. How full you can fill this backpack?
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.
经典背包问题的简化版本,这里求的是背包可以装多满,所以物体的价值这里等于体积.
考虑DP的状态,这里不同于Backpack II, 在体积和前i个约束下考虑价值.
可以从两方面考虑:1.将物体的体积当做物体的价值,f[i][j]为取前i个物体,在最大容量为j的情况,可以获得的最大容量. 听起来很矛盾,但是实际非常符合背包问题的特性,即虽然容量在那里,但是你可能就是无法组合到刚刚填满容量的组合.2.将f[i][j]定义为前i个物体能否组成体积j,能为True, 否则为False.
两种的初始化:1.f[0][j] = 0, 2.f[0][0] = True, f[0][j] = False, 注意2这里是探讨能否装满,所以参考Backpack II中的讨论, 初始化要有所不同.
最终答案: 1. f[n][m], 2.因为是dp存储的是能否的状态,所以我们需要从m超前遍历f[n][j],第一个为True的j就是最大容量.
做法一代码:
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 def backPack(self, m, A): dp = [0] * (m+1) for i in xrange(len(A)): for j in xrange(m, A[i]-1, -1): dp[j] = max(dp[j], dp[j-A[i]] + A[i]) return dp[m]
时间复杂度为O(m*n), 空间复杂度为O(m).
做法二java代码,来自九章:
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) { boolean f[][] = new boolean[A.length + 1][m + 1]; for (int i = 0; i <= A.length; i++) { for (int j = 0; j <= m; j++) { f[i][j] = false; } } f[0][0] = true; for (int i = 0; i < A.length; i++) { for (int j = 0; j <= m; j++) { f[i + 1][j] = f[i][j]; if (j >= A[i] && f[i][j - A[i]]) { f[i + 1][j] = true; } } // for j } // for i for (int i = m; i >= 0; i--) { if (f[A.length][i]) { return i; } } return 0; } }
这个解法没有使用滚动数组优化,如果进行优化,第一个二维for循环可以省略,但是最后一个找最大值的一维循环无法省略.所以做法一的时间上更优.
标签:
原文地址:http://www.cnblogs.com/sherylwang/p/5626356.html