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

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

# 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

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 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 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 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[] must be 1, and dp[] must all be derived from dp 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 = 1;
for (int i = 1; i <= row; i++) {
// Layer 2 backpack size starts at 0 because dp[] 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 = 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) 