| tags |
|
|---|
Prerequisite knowledge: Introduction to Dynamic Programming
Consider the following example:
There are
In the example above, each object has only two possible states (taken or not taken), corresponding to binary 0 and 1. Thus, this type of problem is called "0-1 knapsack problem".
In the example above, the input to the problem is the following: the weight of
Let
Assuming that all states of the first
- When it is not put into the knapsack, the remaining capacity remains unchanged and total value does not change. Therefore, the maximum value in this case is
$f_{i-1, j}$ - When it is put into the knapsack, the remaining capacity decreases by
$w_{i}$ and the total value increases by$v_{i}$ , so the maximum value in this case is$f_{i-1, j-w_i} + v_i$
From this we can derive the dp transition equation:
Further, as
that should be executed in the decreasing order of
It is important to understand this transition rule, because most of the transitions for knapsack problems are derived in a similar way.
The algorithm described can be implemented in
for (int i = 1; i <= n; i++)
for (int j = W; j >= w[i]; j--)
f[j] = max(f[j], f[j - w[i]] + v[i]);Again, note the order of execution. It should be strictly followed to ensure the following invariant: Right before the pair
The complete knapsack model is similar to the 0-1 knapsack, the only difference from the 0-1 knapsack is that an item can be selected an unlimited number of times instead of only once.
We can refer to the idea of 0-1 knapsack to define the state:
It should be noted that although the state definition is similar to that of a 0-1 knapsack, its transition rule is different from that of a 0-1 knapsack.
The trivial approach is, for the first
This yields the following transition equation:
At the same time, it simplifies into a "flat" equation:
The reason this works is that
Similar to the 0-1 knapsack, we can remove the first dimension to optimize the space complexity. This gives us the same transition rule as 0-1 knapsack.
The algorithm described can be implemented in
for (int i = 1; i <= n; i++)
for (int j = w[i]; j <= W; j++)
f[j] = max(f[j], f[j - w[i]] + v[i]);Despite having the same transition rule, the code above is incorrect for 0-1 knapsack.
Observing the code carefully, we see that for the currently processed item
Multiple knapsack is also a variant of 0-1 knapsack. The main difference is that there are
A very simple idea is: "choose each item
The time complexity of this process is
We still consider converting the multiple knapsack model into a 0-1 knapsack model for optimization. The time complexity
Let
The grouping is made more efficient by using binary grouping.
Specifically,
Through the above splitting method, it is possible to obtain any sum of
This optimization gives us a time complexity of
index = 0;
for (int i = 1; i <= n; i++) {
int c = 1, p, h, k;
cin >> p >> h >> k;
while (k > c) {
k -= c;
list[++index].w = c * p;
list[index].v = c * h;
c *= 2;
}
list[++index].w = p * k;
list[index].v = h * k;
}In this optimization, we aim to convert the knapsack problem into a maximum queue one.
For convenience of description, let $g_{x, y} = f_{i, x \cdot w_i + y} ,\space g'{x, y} = f{i-1, x \cdot w_i + y}$. Then the transition rule can be written as:
Further, let
This transforms into a classic monotone queue optimization form.
The mixed knapsack problem involves a combination of the three problems described above. That is, some items can only be taken once, some can be taken infinitely, and some can be taken atmost
The problem may seem daunting, but as long as you understand the core ideas of the previous knapsack problems and combine them together, you can do it. The pseudo code for the solution is as:
for (each item) {
if (0-1 knapsack)
Apply 0-1 knapsack code;
else if (complete knapsack)
Apply complete knapsack code;
else if (multiple knapsack)
Apply multiple knapsack code;
}