Leetcode Brush Title Note - Backpack Problem in Dynamic Planning: 01 Backpack

Posted by vbzoom.com on Sat, 26 Feb 2022 18:27:33 +0100

Catalogue of Series Articles

I. Array Type Solution Method I: Dichotomy
2. Array Type Solution Method 2: Double Pointer Method
3. Array Type Solution Method 3: Sliding Window
IV. Array Type Solution Method 4: Simulation
V. Basic Operation and Classical Title of Chain List in Chain Table Text
6. Classic Title of Hash Table
7. Classic Title of String Text
8. KMP of String Text
9. Solution: Double Pointer
10. Classic Title of Stacks and Queues
11. top-K Problem in Stack and Queue Papers
Twelve, Binary Tree Text Binary Tree Front-Middle-Back Traversal
Thirteen, Binary Tree Text Binary Tree Sequence Traversal and Related Topics
14, Binary Tree Text Binary Tree Properties Related Topics
Fifteen, Modification and Construction of Binary Tree in Binary Tree Text
16, Binary Search Tree Properties for Binary Tree Texts
Seventeen, Common Ancestors of Binary Tree Text
Eighteen, Modification and Construction of Binary Search Tree in Binary Tree Text
Nineteen, Combination of Backtracking Algorithms Text
20, Partitioning, Subset, Full Arrangement of Backtrace Algorithms Text
Twenty-one, Introduction to Greedy Algorithms
Twenty-two, Advanced topics in Greedy Algorithms
Twenty-three, Foundation of Dynamic Planning Text
Updating...

Preface

A product that can be repeated multiple times is a full backpack, but can only be placed once is a 01 Backpack
Brush the title from: Code Casual Recording

Catalogue

01 Backpack problem

LintCode Link
There are n items and a backpack of size m. The given array A represents the size of each item and the array V represents the value of each item. What is the total value of a backpack at most?

Questions:

    /**
     * Status F(i,j): Maximum value of the first iitems in a backpack of size J
     * Recursive relationship: A(i-1) < J when new items cannot be placed in the current backpack:
     *              F(i,j) = F(i-1,j)
     *     When put down: F(i, j) = max{(F(i-1, j), F(i-1, F(j-A(i-1)) + V(i-1)}
     *     A(i-1):  Size of new items
     *     V(i-1):  Price of new items
     *     F(i-1,j): Indicates that item i I is not put in the backpack, so its value is the maximum value of the first i-1 items in a j-sized Backpack
     *     F(i-1, j - A[i]) + V[i]: Indicates that the value of item I I is increased by V[i], but the size of j - A[i] needs to be freed up
 Item i
     *     Initial state: F(i,0) = F(0,j) = 0 Row 0 and Column 0 are both 0, indicating that the value is 0 when nothing is loaded
     *     Return value: F(i,j)
     */
public class Solution {
    public int backPackII(int m, int[] A, int[] V) {
        int row = A.length;
        if (row == 0 || m == 0) return 0;
        int[][] dp = new int[row + 1][m + 1];
        for (int i = 1; i <= row; i++) {    // Traversal Backpack
            for (int j = 1; j <= m; j++) {  // Traversal weight
                if (A[i - 1] > j) {
                	// The quality of the new items is larger than the current backpack and will not fit
                    dp[i][j] = dp[i - 1][j];
                } else {
                	// Put it in. If you want to calculate the remaining size of your backpack when putting in new items, see how much the remaining backpack size can hold at most and then add the price of the new items, and compare the maximum price of your backpack without putting in new items to get the maximum. Maximum prices are all on the top floor
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - A[i - 1]] + V[i - 1]);
                }
            }
        }
        return dp[row][m];
    }
}

Spatial optimization: one-dimensional dp array (rolling array)

  1. Instead of looking in the upper dp array for the maximum value, modify it on the original array and traverse backwards and forwards, since you need to look forward to find the maximum value of the items that can be dropped in the rest of the backpack.
  2. While traversing, if the backpack space is greater than or equal to the value of the new item, traversing forward requires a judgment as to whether the item can be dropped or not, and it is meaningless that the value in the array will not change if it cannot be placed.
public class Solution {
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @param V: Given n items with value V[i]
     * @return: The maximum value
     */
    public int backPackII(int m, int[] A, int[] V) {
        int row = A.length;
        if (m == 0) return 0;
        int[] dp = new int[m + 1];
        for (int i = 0; i < row; i++) {
            for (int j = m; j >= A[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - A[i]] + V[i]);
            }
        }
        return dp[m];
    }
}

416. Split equal and subset

Leetcode Link

Questions:
The whole array is sum, find a subarray of sum / 2
Method 1: Backtracking (result timeout)
The following two questions are almost the same. You can use backtracking to solve the following two questions
698. Divided into k equal subsets
473. Match Matching Square

class Solution {
    boolean flag = false;
    int sumDfs = 0;
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if (sum % 2 == 1) return false;
        sum = sum / 2;
        dfs(nums, sum, 0);
        return flag;
    }
    public void dfs(int[] nums, int sum, int start) {
        if (sumDfs > sum) {
            return;
        }
        if (sumDfs == sum) {
            flag = true;
            return;
        }

        for (int i = start; i < nums.length; i++) {
            sumDfs += nums[i];
            dfs(nums, sum, i + 1);
            sumDfs -= nums[i];
        }
    }
}

Method 2: Dynamic programming (where a one-dimensional dp array is used directly)
Backpack size is sum / 2, items are numeric values in the array, items are num[i] in size and price
dp[i] can be directly regarded as a backpack of size i, the maximum sum of the items to be loaded.
Return value: dp[sum / 2] == sum / 2, sum / 2 Size Backpack just loads sum / 2's maximum sum

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if (sum % 2 == 1) return false;
        sum = sum / 2;
        
        int[] dp = new int[sum + 1];
        for (int i = 0; i < nums.length; i++) {
            for (int j = sum; j >= nums[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }
        return dp[sum] == sum;
    }
}

1049. Weight of the last stone II

Leetcode Link

1046. Weight of the last stone
Change any stone of the body into two distinct questions of the two largest stones and use a priority queue to solve them
Questions:
Difficulty point: how can I get into dp? Look at the explanation of the great God Trifoliate
The commentary area bully is a mystery breaker:
Because every offset is actually the process of [a, b,...] becoming [a - b,...] or [b-a,...], eventually a calculation like (b - a) - (c - d) that flattens -a + b - c + d = (b+d)-(a+c), B + D >= sum/2 >= a+c, all you need to do is find the maximum value when a+c is not greater than sum/2, classical backpack problem.
dp[v] - (a + c) = b + d, return (b + d) - (a + c)
Return value: sum - dp[v] - dp[v]; Front sum - dp[v] gets a larger sum

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        for (int i : stones) {
            sum += i;
        }
        int v = sum / 2;
        int[] dp = new int[v + 1];
        for (int i = 0; i < stones.length; i++) {
            for (int j = v; j >= stones[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
            }
        } 
        // Notice what the return value means
        return sum - dp[v] - dp[v]; 
    }
}

494. Goals and objectives

Leetcode Link

Questions:
By bigSum - smallSum = target, bigSum + smallSum = sum
Get smallSum = (sum - target) / 2 (because smallSum < bigSum), so choose smallSum here, and the formulas are known to be non-negative even numbers.
The number of expressions that result in how many operations equals a target is determined by the number of subcombinations of bigSum or smallSum where bigSum - smallSum = target. So this question is equivalent to asking: sum the maximum number of combinations of subarrays of bigSum or smallSum can be used as 01 knapsack problem.
The backpack size is determined by smallSum and the item size is nums[i].
Dp[i][j]: Maximum number of combinations of 0~i items in a backpack of size J

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int row = nums.length;
        int sum = 0;
        for (int i : nums) {
            sum += i;
        }
        // And are both less than target, returning 0
        if (sum - target < 0) return 0;
        if ((sum - target) % 2 == 1) return 0;
        // SmllSum is a non-negative even number;
        int smallSum = (sum - target) / 2;
        
        int[][] dp = new int[row + 1][smallSum + 1];
        // Dp[][0] must be 1, and dp[][0] must all be derived from dp[0][0] because, when it happens to be dropped, a 1 is added to the maximum number of combinations that do not want the item (only the item is placed).
        dp[0][0] = 1;
        for (int i = 1; i <= row; i++) {
        	// Layer 2 backpack size starts at 0 because dp[][0] must be 1
            for (int j = 0; j <= smallSum; j++) {
                if (j >= nums[i - 1]) {
                	// When ready, the maximum number of combinations dp[i-1][j] before placing, plus the maximum number of combinations after placing = the maximum number of combinations whose size is j-num[i-1] before placing
                	// Num[i-1]:0 Item Subscript starts from 1, so it is I-1 for new items
                	// j - num[i - 1]: the size left in the backpack
                    dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]];
                } else {
                	// When it doesn't fit
                    dp[i][j] = dp[i - 1][j];
                }   
            }
        }
        return dp[row][smallSum];
    }
}

Spatial optimization (one-dimensional scrolling dp array):

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int row = nums.length;
        int sum = 0;
        for (int i : nums) {
            sum += i;
        }
        if (sum - target < 0) return 0;
        if ((sum - target) % 2 == 1) return 0;
        int smallSum = (sum - target) / 2;
        
        int[] dp = new int[smallSum + 1];
        dp[0] = 1;
        for (int i = 0; i < row; i++) {
            for (int j = smallSum; j >= nums[i]; j--) {
                dp[j] = dp[j] + dp[j - nums[i]];
            }
        }
        return dp[smallSum];
    }
}

474.1 and zero (rolling 2-D dp)

Leetcode Link

summary

  1. Recursive formula for maximum and type
    Dp[i][j] = Math. Max (dp[i-1][j], dp[i-1][j-A[i-1]] + V[i-1]); After dimension reduction: dp[j] = Math. Max (dp[j], dp[j-A[i] + V[i]);
  2. Recursive Formula for Combination Type
    Dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]; After dimension reduction: dp[j] = dp[j] + dp[j - nums[i];

Topics: Java Algorithm leetcode Dynamic Programming