美文网首页
背包问题

背包问题

作者: 石榴蒂凡尼_21e4 | 来源:发表于2017-11-05 04:01 被阅读0次

    题目:backpack I (每个物品取一次,求最多能装多少物品)

    Given n items with size Ai, an integer m denotes the size of a backpack. How full can you fill this backpack?

    Input:

    • 物品的大小:: int[]
    • 背包的大小 ::int

    Output:

    • 背包最多能装多少:: int

    Intuition:

    典型的DP问题,dp array存档背包大小为j时,dp[i]表示在装或者不装第 i - 1号物品时最多能装多少物品。

    • 不装第 i 号的物品: dp[i - 1][j]
    • 装第 i 号物品: dp[i - 1][j - A[i - 1]] + A[i - 1]
      举个例子: 物品大小[3, 4, 8, 5], 背包size为10
      那么在每次装一个物品时,dp array的更新如下:
      Array List: 0 0 0 3 3 3 3 3 3 3 3
      Array List: 0 0 0 3 4 4 4 7 7 7 7
      Array List: 0 0 0 3 4 4 4 7 8 8 8
      Array List: 0 0 0 3 4 5 5 7 8 9 9

    Code:

    TC: (nm) SC: (nm)

    public int backPack(int m, int[] A) {
            // write your code here
            if (A == null || A.length == 0){
                return 0;
            }
            
            int[][] dp = new int[A.length + 1][m + 1];
            
            for (int i = 1; i <=A.length; i++){
                for (int j = 0; j <= m; j++){
                
                    if (j >= A[i - 1]) {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - A[i - 1]] + A[i - 1]);
                    } else {
                        dp[i][j] = dp[i - 1][j];
                    }
                  
                }
            }
            return dp[A.length][m];
        }
    

    当然,遇到二维数组的时候我们会考虑是不是要进行空间压缩,使用一维数组。

    TC: (nm) SC: (m)

    Code:

     public int backPack(int m, int[] A) {
            // write your code here
            if (A == null || A.length == 0){
                return 0;
            }
            
            int[] dp = new int[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];
        }
    

    题目:backpack II (每个物品取一次,求最多能装物品的最大价值)

    Given n items with size Ai and value Vi, and a backpack with size m. What's the maximum value can you put into the backpack?

    Input:

    • 物品的大小:: int[]
    • 物品的价值:: int[]
    • 背包的大小 ::int

    Output:

    • 背包能装物品的最大价值:: int

    Intuition:

    基本思想和backpack I是一样的,不同之处就在于我们更新的是物品的价值而不是物品的大小。

    • 不装第 i 号的物品: dp[i - 1][j]
    • 装第 i 号物品: dp[i - 1][j - A[i - 1]] + V[i - 1]
      例子: 物品大小[2, 3, 5, 7], 物品价值[1, 5, 2, 4],背包size为10
      那么在每次装一个物品时,dp array的更新如下:
      Array List: 0 0 1 1 1 1 1 1 1 1 1
      Array List: 0 0 1 5 5 6 6 6 6 6 6
      Array List: 0 0 1 5 5 6 6 6 7 7 8
      Array List: 0 0 1 5 5 6 6 6 7 7 9

    Code:

    TC: (nm) SC: (nm)

    public int backPack(int m, int[] A) {
            // write your code here
            if (A == null || A.length == 0){
                return 0;
            }
            
            int[][] dp = new int[A.length + 1][m + 1];
            
            for (int i = 1; i <=A.length; i++){
                for (int j = m; j >= 0; j--){
                
                    if (j >= A[i - 1]) {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - A[i - 1]] + V[i - 1]);
                    } else {
                        dp[i][j] = dp[i - 1][j];
                    }
                  
                }
            }
            return dp[A.length][m];
        }
    

    同样的可以压缩空间

    Code:

    TC: (nm) SC: (m)

    public int backPackII(int m, int[] A, int[] V) {
            // write your code here
             // write your code here
            if (A == null || A.length == 0){
                return 0;
            }
            
            int[] dp = new int[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]] + V[i]);
                    } 
                }
            }
            return dp[m];
        }
    

    题目:backpack III (每个物品可取无限次,求最多能装物品的最大价值)

    Given n items with size Ai and value Vi, and a backpack with size m. What's the maximum value can you put into the backpack?

    Input:

    • 物品的大小:: int[]
    • 物品的价值:: int[]
    • 背包的大小 ::int

    Output:

    • 背包能装物品的最大价值:: int

    Intuition:

    更新dp array值的策略是一样的。不过这次更新的顺序不再是从后到前,而是反过来了。这样在后半部的更新可以利用之前的值。
    例子: 物品大小[2, 3, 5, 7], 物品价值[1, 5, 2, 4],背包size为10
    那么dp array的更新如下:
    Array List: 0 0 1 1 2 2 3 3 4 4 5
    Array List: 0 0 1 5 5 6 10 10 11 15 15
    Array List: 0 0 1 5 5 6 10 10 11 15 15
    Array List: 0 0 1 5 5 6 10 10 11 15 15

    Code:

    TC: O(nm) SC: O(m)

     public int backPackIII(int[] A, int[] V, int m) {
            // write your code here
           // write your code here
             // write your code here
            if (A == null || A.length == 0){
                return 0;
            }
            
            int[] dp = new int[m + 1];
            
            for (int i = 0; i <A.length; i++){
                for (int j = 0; j <= m; j++){
                
                    if (j >= A[i]) {
                        dp[j] = Math.max(dp[j], dp[j - A[i]] + V[i]);
                    } 
                }
            }
            return dp[m];
        }
    

    题目:backpack IV (每个物品可取无限次,从中找出所有的和为 target 的组合个数)

    Given an integer array nums with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

    Input:

    • 物品的大小:: int[]
    • 目标值 ::int

    Output:

    • 所有的和为目标的组合个数:: int

    Intuition:

    用一个dp array存0到target的可能组合数,dp[i]的组合数可以根据之前组合数求得。 dp[i] += dp[i - num[i]] 或者 dp[i + num[i]] += dp[i]

    Code:

    TC: O(n*m) SC: O(m)

    public int backPackIV(int[] nums, int target) {
            // write your code here
            if(nums == null || nums.length == 0) return 0;
            int[] dp = new int[target + 1];
            
            dp[0] = 1;
            
            
            for(int n: nums){
                for(int i = 0; i <= target; i++){
                    if(n + i <= target){
                        dp[i + n] += dp[i] ;
                    }
                }
            }
            return dp[target];
        }
    

    题目:backpack V (每个物品可取一次,从中找出所有的和为 target 的组合个数)

    Given an integer array nums with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

    Input:

    • 物品的大小:: int[]
    • 目标值 ::int

    Output:

    • 所有的和为目标的组合个数:: int

    Intuition:

    与上一题不同,单次选择的话更新dp array的顺序应该从后到前。

    Code:

    TC: O(mn) SC: O(m)

    public int backPackV(int[] nums, int target) {
           // write your code here
            if(nums == null || nums.length == 0) return 0;
            int[] dp = new int[target + 1];
            
            dp[0] = 1;
            for(int n: nums){
                for(int i = target; i >= 0; i--){
                    if(n + i <= target){
                        dp[i + n] += dp[i] ;
                    }
                }
            }
            return dp[target];
        }
    

    题目:backpack VI (每个物品可取无限次,数的顺序不同则会被认为是不同的组合,从中找出所有的和为 target 的组合个数)

    Given an integer array nums with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

    Input:

    • 物品的大小:: int[]
    • 目标值 ::int

    Output:

    • 所有的和为目标的组合个数:: int

    Intuition:

    这个题与backpackIV 不同的一点就是同样的数,用在组合不同的位置可认为是有效的解。那么可以理解成,我们在每个size装物品的时候需要每个物品都试一遍,那么对物品size的循环就应该成为内循环了。

    Code:

    TC:O(mn) SC: O(m)

    public int backPackVI(int[] nums, int target) {
            // write your code here
            if(nums == null || nums.length == 0) return 0;
            int[] dp = new int[target + 1];
            
            dp[0] = 1;
             
            for(int i = 0; i <= target; i++){
               for(int n: nums){
                    if(n + i <= target){
                        dp[i + n] += dp[i];
                    }
                }
                printArrayList(dp);
            }
            return dp[target];
        }
    

    相关文章

      网友评论

          本文标题:背包问题

          本文链接:https://www.haomeiwen.com/subject/myftmxtx.html