P01: 01 backpack Problems

Question

There are n items and a backpack with a capacity of v. The cost of the I-th item is C [I], and the value is W [I]. Solving which items are loaded into a backpack can maximize the total value.

Basic Ideas

This is the most basic problem with a backpack. It features that each item has only one item, and you can choose to put it or not.

Define the state with a subproblem: that is, F [I] [v] indicates the maximum value that a backpack with a capacity of V can obtain when the first I item is placed. The state transition equation is:

F [I] [v] = max {f [I-1] [v], F [I-1] [V-C [I] + W [I]}

This equation is very important. Basically all the equations related to the backpack are derived from it. Therefore, it is necessary to explain in detail: "Put the first I items into a backpack with a capacity of V, if you only consider the I-th item Policy (put or not put), then it can be converted into a problem that only involves the previous I-1 items. If I items are not put, then the problem is converted to "pre-i-1 items into the capacity of V backpack", the value is f [I-1] [v]; if I items are placed, the problem is converted to "the previous I-1 items are placed in the backpack with the remaining capacity V-C [I ", the greatest value that can be obtained at this time is f [I-1] [V-C [I] plus the value W [I] obtained by placing the I item.

Optimize space complexity

The time and space complexity of the above method are O (VN). The time complexity should no longer be optimized, but the space complexity can be optimized to O.

First, consider how to implement the basic idea mentioned above. There must be a main loop I = 1 .. n, two-dimensional array f [I] [0 .. all values of V. Then, if only one array f [0 .. v]. can we ensure that f [I] [v] represents the state we defined after the end of the I-th loop? F [I] [v] is derived from two subproblems: F [I-1] [v] and f [I-1] [V-C [I, can we ensure that f [I] [v] is pushed (that is, when f [v] is pushed in the I Main Loop) can we get the values of F [I-1] [v] and f [I-1] [V-C [I? In fact, this requires that in each main loop we use v = V .. 0 in order. f [v], this ensures that f [v] f [V-C [I] saves the value of State f [I-1] [V-C [I. PseudoCodeAs follows:

For I = 1 .. N for V = V .. 0 f [v] = max {f [v], F [V-C [I] + W [I]}; f [v] = max {f [v], f [V-C [I]} is equivalent to our transfer equation f [I] [v] = max {f [I-1] [v], f [I-1] [V-C [I]}, because the current F [V-C [I] is equivalent to the original f [I-1] [V-C [I]. If we change the circular order of V from the forward order to the order, then f [I] [v] is deduced by F [I] [V-C [I, it is not consistent with the meaning of this question, but it is another important backpack problem p02 is the most simple solution, so it is necessary to learn to solve the problem of 01 backpack with only one-dimensional array.

In fact, the one-dimensional array is used to solveProgramIt will be used multiple times later, so here is an abstract process for processing an item in a 01 backpack. It will be called directly in future code without instructions.

Zeroonepack indicates processing an item in a 01 backpack. The two parameters cost and weight indicate the cost and value of this item respectively.

Procedure zeroonepack (cost, weight) for V = V .. cost f [v] = max {f [v], F [V-cost] + weight} note that the processing in this process is different from the pseudo code given above. The preceding example program v = V .. 0 is used to show that every state in the program is solved according to the equation, avoiding unnecessary complexity of thinking. Now that the process has been abstracted as a black box, you can add optimization. Items whose cost is cost will not affect the status f [0 .. cost-1], which is obvious.

With this process, you can write the pseudocode for the 01 backpack problem as follows:

For I = 1. N zeroonepack (C [I], W [I]); Initialization details

We can see that there are actually two different ways to solve the problem of a backpack. Some questions require the optimal solution when "just full of backpacks", and some questions do not require that the backpack be full. One difference is that the implementation methods of these two questions are different during initialization.

If the first method is used, it is required to be filled with a backpack. during initialization, F [0] is 0, and f [1 .. v] is set to-∞, which ensures that the final f [N] is an optimal solution just filled with a backpack.

If you do not need to fill your backpack, but only want the price to be as high as possible, you should set all f [0.. V] to 0 during initialization.

Why? It can be understood as follows: The initialized F array is actually the legal status when no item can be put into a backpack. If a backpack is required to be filled, only a backpack with a capacity of 0 may be filled with nothing with a value of 0. There is no legal solution for a backpack with other capacities, for undefined states, their values should all be-∞. If the backpack does not have to be filled, then any capacity of the backpack has a legal solution: "Nothing is loaded." the value of this solution is 0, therefore, the initial status values are all 0.

This tips can be fully applied to other types of backpack problems, so we will not explain the initialization before the status transfer.

Constant Optimization

In the preceding pseudo code, for V = V .. 1 can be used to improve the lower limit of the loop.

Because we only need the final value of F [v], we only need to know f [V-W [N. Similarly, for the J-ID backpack, you only need to know f [V-sum {W [J .. n]}], that is, in the code

For I = 1 .. n for V = V .. 0 can be changed

For I = 1 .. N bound = max {v-sum {W [I .. n]}, C [I]} For v = V .. bound is useful when V is large.

Summary

01 the backpack problem is the most basic problem. It contains the most basic idea of the design state and equation in the backpack problem. In addition, other types of knapsack problems can also be converted to 01. Therefore, you must carefully understand the methods of the above basic ideas, the significance of the state transition equation, and how to optimize the space complexity.

P02: complete backpack Problems

Question

There are n items and a backpack with a capacity of V, each of which has unlimited items available. The capacity of item I is C [I], and the value is W [I]. Solving which items are loaded into a backpack can make the total capacity of these items not exceed the total capacity of the backpack, and the total value is the largest.

Basic Ideas

This problem is very similar to the 01 backpack problem. The difference is that each item has unlimited items. That is to say, from the perspective of each item, there are no or no two policies related to it, but 0, 1, and 2 ...... And so on. If you still follow the troubleshooting idea of 01, make f [I] [v] to indicate that the first I items are placed in the maximum weight of a backpack with a capacity of v. You can still write the state transition equation based on different policies for each item, as shown in the following code:

F [I] [v] = max {f [I-1] [V-K * C [I] + K * W [I], f [I-1] [v]} (0 <= K * C [I] <= V)

This is the same as the 0th backpack problem. There are O (VN) states that need to be solved, but the time for solving each State is no longer a constant, the time for solving the state f [I] [v] is O (V/C [I]), the overall complexity can be considered O (V * Σ (V/C [I]), which is relatively large.

I improved the basic idea of the backpack problem and obtained such a clear method. This shows that the equation of the 01 knapsack problem is indeed very important, and can be considered as another type of knapsack problem. But we are still trying to improve this complexity.

A simple and effective optimization

There is a very simple and effective optimization for the full backpack problem, as shown in the following code: if two items I and j meet the requirements of C [I] <= C [J] and w [I]> = W [J], remove item j. The correctness of this optimization is obvious: under any circumstances, you can replace the small-cost high-value J with inexpensive I, and get at least no worse solution. For randomly generated data, this method often greatly reduces the number of items, thus accelerating the speed. However, this does not improve the complexity of the worst case, because it is possible that specially designed data cannot be removed from an item.

This optimization can be implemented in a simple O (N ^ 2) manner and is generally acceptable. In addition, one of the better solutions for the knapsack problem is: first remove items with a capacity greater than V, and then use a similar counting sorting method, calculate which of the items with the same capacity has the highest value (as long as the item with the same value is retained, the same as the filtering above), and can be O (V + n) to complete the optimization. This unimportant process does not provide pseudocode. I hope you can think about writing pseudocode or programs independently.

Convert to 01 solve the Knapsack Problem

Since the question 01 is the most basic question about a backpack, we can consider converting the question of a full backpack into a question 01 about a backpack. The simplest idea is to select at most V/C [I] items for the I-th item, therefore, you can convert the I-th item to an item with the same capacity and value as the V/C [I] item, and then solve this 01 backpack problem. In this way, there is no time complexity to improve the basic idea, but this gives us the idea of converting a full backpack problem into a 01 backpack problem: Splitting an item into multiple items.

A more efficient conversion method is to split the I-th item into several items with a capacity of C [I] * 2 ^ K and a value of W [I] * 2 ^ K, k meets C [I] * 2 ^ k <= v. This is a binary idea, because no matter how many items of the I-th item are selected in the optimal strategy, they can always be expressed as the sum of several 2 ^ K items. In this way, splitting each item into an O (log V/C [I]) item is a great improvement.

But we have a better O (VN)Algorithm.

O (VN) Algorithm

This algorithm uses a one-dimensional array. first look at the pseudo code:

For I = 1 .. N for V = 0 .. V f [v] = max {f [v], F [V-cost] + weight} you will find that this pseudo code is different from p01's pseudo code except V's loop order. Why is this change feasible? First, let's think about why the V = V .. 0 in p01 should be reversed. This is because we need to ensure that the State f [I] [v] in the I-th loop is recursive from the state f [I-1] [V-C [I. In other words, this is to ensure that each item is selected only once, and to ensure that the policy of "selecting the I-item" is considered, it is based on a sub-result f [I-1] [V-C [I] That has never been selected for item I. Now, the unique feature of a backpack is that each type of item can be an unlimited number of items. Therefore, when considering the policy of "adding a first item, however, you need a sub-result f [I] [V-C [I] that may have been selected for Type I. Therefore, you can use V = 0 .. v. This is why this simple program is established.

It is worth mentioning that the order of the two-layer for loop in the above pseudo code can be reversed. This conclusion may lead to optimization of the algorithm time constant.

This algorithm can also be derived from other ideas. For example, explicitly write the state transition equation for solving f [I] [V-C [I] in the basic idea into the original process, we will find that this equation can be equivalent to this form:

F [I] [v] = max {f [I-1] [v], F [I] [V-C [I] + W [I]}

This equation is implemented using a one-dimensional array and the above pseudo code is obtained.

Finally, the process of abstracting the source to handle a complete backpack-type item is pseudocode:

Procedure completepack (cost, weight) for V = C [I] .. V f [v] = max {f [v], F [V-C [I] + W [I]} Summary

The complete knapsack problem is also a very basic knapsack problem. It has two state transfer equations, which are given in the section "basic idea" and "O (VN) algorithm" respectively. I hope that you can carefully understand these two state transition equations, not only remember, but also understand how they come out. It is best to think of a method to obtain these equations on your own. In fact, it is a good way to deepen understanding of dynamic planning and improve the skill of dynamic planning to think about the significance of its equation and how to obtain it.

P03: Multiple knapsack problems

Question

There are n items and a backpack with a capacity of v. A maximum of N [I] items are available for Type I. The capacity of each item is C [I] and the value is W [I]. Solving which items are loaded into a backpack can make the total capacity of these items not exceed the total capacity of the backpack, and the total value is the largest.

Basic Algorithms

This is similar to a full backpack problem. The basic equation only needs to slightly change the equation of the complete backpack problem, because there are N [I] + 1 strategy for the I-th item: Take 0, take 1 ...... N [I] parts. If f [I] [v] indicates that the first I items are placed in the maximum weight of a backpack with a capacity of V, there is a state transition equation:

F [I] [v] = max {f [I-1] [V-K * C [I] + K * W [I], f [I] [v]} (0 <= k <= N [I])

The complexity is O (V * Σ N [I]).

Converting to 01 backpack Problems

Another basic way to write well is to convert it to 01 backpack solution: Replace the I-th item with the item in the N [I] Piece 01 backpack, then, the 01 backpack problem with the number of items is obtained. The problem is solved directly, and the complexity is still O (V * Σ N [I]).

But we expect that it will reduce complexity as if it were a full backpack after converting it into a 01 backpack problem. We still consider the binary idea. We want to replace the I-th item with several items, so that in the original question, the I-th item can be used in every strategy -- 0 .. N [I] parts-can be equivalent to several replacement items. In addition, a policy that exceeds N [I] parts cannot appear.

The method is to divide the I-th item into several items, each of which has a coefficient. The capacity and value of this item are the original capacity and value multiplied by this coefficient. Make these coefficients respectively 1, 2, 4 ,..., 2 ^ (k-1), N [I]-2 ^ k + 1, and K is the maximum integer that satisfies N [I]-2 ^ k + 1> 0. For example, if n [I] is 13, the item is divided into four items with a coefficient of 1, 2, 4, and 6.

The coefficient of the divided items is n [I], indicating that the I-th item cannot be obtained more than N [I] items. In addition, this method can ensure that 0 .. each integer between N [I] can be expressed by the sum of several coefficients. This proof can be divided into 0 .. 2 ^ K-1 and 2 ^ K .. N [I] is not difficult to discuss separately. I hope you can think about it yourself.

In this way, the I-th item is divided into O (log2n [I]) items, and the original problem is converted to O (V * Σ log2n [I]). the 0th backpack problem is a great improvement.

The following describes how o (log amount) processes items in multiple backpacks. amount indicates the number of items:

Procedure multiplepack (cost, weight, amount) If cost * Amount> = V // if there are enough I items, then it is equivalent to an infinite number of completepack (cost, weight) // complete backpack processing return integer k = 1 while K <amount zeroonepack (K * cost, K * weight) Amount = amount-k = K * 2 zeroonepack (Amount * cost, amount * weight) I hope you can understand this pseudocode carefully. If you do not understand it, translate it into the program code and execute it several times in a single step, or use a pen or paper to simulate it, it may be easy to understand.

O (VN) Algorithm

Multiple knapsack problems also involve O (VN) algorithms. This algorithm is based on the state transition equation of the basic algorithm, but the monotonic queue method is used to make the values of each State be solved at an average O (1) time. Since the DP optimized with monotonous queue is beyond the scope of noip, this article will not explain it further. I first learned that this method was on Lou Tiancheng's "Man's eight questions" slide.

Summary

Here we see the process of improving the complexity of an algorithm from O (V * Σ N [I]) to O (V * Σ log n [I, we also know that there is an O (VN) algorithm that applies knowledge beyond the noip range. I hope you will pay special attention to the idea and method of "splitting items", prove its correctness, and write the complete program code.

P04: mixed three backpack Problems

Problem

If you mix p01, p02, and P03. That is to say, some items can be taken only once (01 backpack), some items can be taken unlimited times (full backpack), and some items can be taken up to a maximum of times (multiple backpacks ). How should we solve it?

01 mixing a backpack with a full backpack

Because the pseudocode given in p01 and p02 is only one different, if there are only two types of items: one type of item can only be retrieved once, and the other type of items can be retrieved infinitely, when you apply the transfer equation to each item, you only need to select an order or backward Loop Based on the item category. The complexity is O (VN ). The pseudocode is as follows:

For I = 1 .. n if the I-th item belongs to 01 backpack for V = V .. 0 f [v] = max {f [v], F [V-C [I] + W [I]}; else if the I-th item belongs to the full backpack for V = 0 .. V f [v] = max {f [v], F [V-C [I] + W [I]}, plus multiple backpacks

If you can add up to a limited number of items, you can also give an O (VN) solution in principle: You can solve multiple types of items in a monotonous queue. However, if you do not consider the algorithm that exceeds the noip range, you can use P03 to divide each of these items into items in the O (log n [I]) 001 backpack.

Of course, a clearer way of writing is to call the three relevant processes we mentioned earlier.

For I = 1 .. n if the I-th item belongs to 01 backpack zeroonepack (C [I], W [I]) else if the I-th item belongs to the complete backpack completepack (C [I], W [I]) else if the I-th item belongs to multiplepack (C [I], W [I], n [I]) when we first wrote these three processes, we probably did not think they would be mixed here. I think this shows the power of abstraction in programming. If you have been writing each type of backpack problem in this "abstract process" way, you are also very aware of the differences in their implementations, so when we encounter the problem of mixing three backpacks, we will be able to quickly think of the simple solution above, right?

Summary

Some people say that difficult questions are all superimposed by simple questions. Whether or not this sentence is still true or not, but it has been fully reflected in this lecture. Originally 01 backpacks, full backpacks, and multiple backpacks are not difficult, but after they are simply Combined, they will have such a question that will surely scare many people. However, as long as you have a solid foundation and understand the ideas of the three basic knapsack problems, you can split the difficult questions into simple ones to solve them.