Discussion on Traversal Order of Complete Knapsack in DP

First review the definitions of several knapsack problems:
01 knapsack: each item can only be taken or not taken two states
Complete knapsack: each item can be taken infinitely many times
Multiple knapsack: each item can be taken multiple times, but the number of times is different

As we all know, the 01 backpack can exchange the order of the items and the order of the backpack arbitrarily using the two-dimensional dp. If you use the one-dimensional dp, you must first carry the items and then carry the backpack, and the backpack is in reverse order, otherwise the items will be taken repeatedly. The reason for the reverse traversal is that it is essentially a one-to-two dimensional array, and the value in the lower right corner depends on the value in the upper left corner of the previous layer, so it is necessary to ensure that the value on the left is still from the previous layer, covering from right to left. The order of the two for loops of the complete backpack is all possible.

Note that the calculation of the pure complete knapsack is whether the sum can be made up, that is, the maximum weight (maximum value) that can be made up is stored in the dp array. The order is fine too! Therefore, some questions need to be considered more if they involve the order. Use change exchange ② as an example:

You are given an integer array coins representing coins of different denominations, and an integer amount representing the total amount.

Please calculate and return the number of coin combinations that can make up the total amount. Returns 0 if no combination of coins can add up to the total amount.

Suppose there are an infinite number of coins of each denomination.

The title data guarantees that the result fits into a 32-bit signed integer.

Example 1:

Input: amount = 5, coins = [1, 2, 5]
Output: 4
Explanation: There are four ways to make up the total amount:
5=5
5=2+2+1
5=2+1+1+1
5 =1+1+1+1+1
Example 2:

Input: amount = 3, coins = [2]
Output: 0
Explanation: Only coins of denomination 2 cannot make up the total amount of 3.
Example 3:

Input: amount = 10, coins = [10]
Output: 1

The amount of code is very small:

class Solution {
    
    
public:
    int change(int amount, vector<int>& coins) {
    
    
        vector<int> dp(amount + 1, 0);
        dp[0] = 1;
        for (int i = 0; i < coins.size(); i++) {
    
     // 遍历物品
            for (int j = coins[i]; j <= amount; j++) {
    
     // 遍历背包
                dp[j] += dp[j - coins[i]];
            }
        }
        return dp[amount];
    }
};

If we swap the order:

for (int j = 0; j <= amount; j++) {
    
     // 遍历背包容量
    for (int i = 0; i < coins.size(); i++) {
    
     // 遍历物品
        if (j - coins[i] >= 0) dp[j] += dp[j - coins[i]];
    }
}

You will find that the test case cannot be passed. Here is a picture to explain the reason:
In the first case, combine the code to understand:
insert image description here

The second case:
insert image description here
Summary:
 If you want to find the number of combinations, the outer for loop traverses the items, and the inner for traverses the backpack.
 If you want to find the number of permutations, the outer for loop traverses the backpack, and the inner loop traverses the items.

Guess you like

Origin blog.csdn.net/qq_42567607/article/details/125759803