• Backpack


    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循环可以省略,但是最后一个找最大值的一维循环无法省略.所以做法一的时间上更优.

  • 相关阅读:
    [Python] xrange和range的使用区别
    安装ipython notebook及基本命令(快捷键)
    Django model 反向引用中的related_name
    Django模板系统——过滤器
    介绍Git的17条基本用法
    Hive HBase 整合
    Hive的动态分区
    Hive中的数据库(Database)和表(Table)
    Hive中数据的加载和导出
    Hive入门--2.分区表 外部分区表 关联查询
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5626356.html
Copyright © 2020-2023  润新知