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

  • 相关阅读:
    Webpack 入门指迷--转载(题叶)
    浏览器工作原理理解
    Knockout.js初体验
    node.js链接mysql
    2020年度春季学习总结--第二周
    Python 爬取 热词并进行分类数据分析-[安全性改造]
    以 CheatEngine 为例的六个质量属性
    2020年度春季学习总结--第一周
    软件架构师如何工作-个人见解
    Steam 游戏 《Crashlands(崩溃大陆)》修改器制作-[先使用CE写,之后有时间的话改用CheatMaker](2020年寒假小目标12)
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5626356.html
Copyright © 2011-2022 走看看