Knapsack problem is a kind of very typical dynamic programming problem, including many types (01 backpack, full backpack, multiple backpack, mixed backpack, two-dimensional cost backpack, etc.) its basic type is 01 knapsack problem.

**One, 01 knapsack problem**
n items, the weight and value of each item are W[i], v[i], put these items into a backpack with a capacity of W, to find the maximum value of the items in the backpack.

Formal definition:

**Analysis**

The most intuitive idea is to enumerate all possible combinations of items that appear in the backpack, and then calculate their value and the maximum value. If recursive search directly, there will be a lot of redundancy, through the memory of the search method can be improved (memory max[i][w], the total weight of items in the previous I to the maximum value of W, where I and W is the parameters of the recursive function). The dynamic planning method can be further improved.

In order to consider the optimal substructure and the no-effect in the dynamic programming, it is assumed that the former I-1 items have a maximum value and m under the weight and constraint W, so when considering the maximum m ' value of the first item in weight and constraint w ', we only care about the weight of the former I-1 and W and Max value and M, As for this former i-1, how to choose the solution M ' without effect (because m ' = m + v[i], assuming w + w[i] = W '), that is, no effect, and the first I item under the weight constraint W ' under the value of the maximum value, at this time the selection of items set to S, Then s must contain a combination of the top i-1 items under the weight constraint W (w = w ' or w = W '-w[i]) (as proved by the counter-evidence method), i.e. the optimal substructure.

Consider, therefore, that the issue is defined as `前i种物品总重量不超过w时，能够得到的最大价值 f[i][w]`

. There are **recursive formulas** at this point

F[I][W] = max (F[i-1][w], F[i-1][w-w[i]] + v[i]) //Case 1. Do not select Article I items, then the maximum value of the first I can be obtained is f[i-1][w]; Case 2. Select Item I, then the former i-1 species can use w-w[i] space storage, the first i-1 species can be the maximum value f[i-1][w-w[i]], plus the value of the article I items v[i] //In the middle of the two to take the maximum value.

Setting **boundary conditions** for practical problems

Apparently I>=0, w>=0. F[0][W] means that when no item is selected, the total weight does not exceed W, the value obtained and the maximum value, obviously 0, i.e. f[0][w] = 0; F[i][0] represents the items in the front I, the total weight and not exceeding 0, the maximum value and the value, because the weight of the problem is a positive integer, so, obviously 0, that is f[i][0] = 0.

**Optimized**

As can be seen, f[i][xx] only and f[i-1][yy], assuming that there is currently a one-dimensional array, storing the first i-1 items under a certain constraint XX maximum value, you can directly find the first I items under a constraint yy maximum value. So you can use a one-dimensional array to scroll through the two-dimensional array for space optimization (more visually by drawing).

F[I][W] = max (F[i-1][w], F[i-1][w-w[i]] + v[i]), change to a one-dimensional array f[w] = max (F[w], F[w-w[i]] + v[i]), in a one-dimensional array, the weight w is only related to W and w-w[i], so from Forward recursion (if from front to back, causes the value after the modified value x to be modified on the basis of the new X (i.e., the top I item selection) and does not conform to the requirements for selection in the previous i-1 items.

**Realize**

for (int i = 0; I <= W; i + +) { f[w] = 0;} for (int i = 1; I <= n; i + +) {for (int w = w; w >= W[i]; W--) { f[w] = max (F[w], F[w-w[i]] + v[i]); }}

**Analysis of Complexity**

After space optimization, the space complexity is O (W) and the time complexity is O (n*w).

**second, complete knapsack problem**
There are n kinds of items, each item has a weight of w[i] and value v[i], each item can choose an unlimited number of pieces. Given a backpack that does not weigh more than W, find out the value and maximum value of the items placed in the backpack.

As with the 01 knapsack problem, F[i][w] represents the maximum value and value of the items in the top I item that have been selected for a total weight not exceeding W. Yes

F[I][W] = Max{f[i-1][w-k*w[i]] + k*v[i]} | K belongs to [0, W/w[i]]

**Analysis**

Observe f[i][w] = Max{f[i-1][w-k*w[i]] + k*v[i]} | K belongs to [0, W/w[i]], Max{f[i-1][w-k*w[i]] + k*v[i]} = Max{f[i-1][w], F[i-1][w-k*w[i]] + k*v[i]} | k belongs to [1, w/w[i]],
K = T+1, then Max{f[i-1][w-k*w[i]] + k*v[i]} | k belongs to [1, W/w[i]], = max{f[i-1][w-w[i]-t*w[i]] + t*v[i]} + v[i] | t belongs to [0, (W-w[i])/w[i]], = f[i-1][w-w[i]] + v[i] so f[i][w] = max{f[i-1][w], F[i-1][w-w[i]] + v[i]}

Recursive formulations are therefore simplified in order to ** **`f[i][w] = max{f[i-1][w], f[i-1][w-w[i]] + v[i]}`

For this formula, it can be understood that: in seeking f[i][w] [Max{f[i-1][w-k*w[i]] + k*v[i]}, and in the F[i][w-w[i]], has been asked for Max{f[i-1][w-k*w[i]] + k*v[i]} F[i-1][w-w[i]], you can continue to roll out f[i][w], without having to repeat Max{f[i-1][w-k*w[i]] + k*v[i]}.

Similarly, a one-dimensional array can be used for spatial optimization to get a recursive formula

`f[w] = max{f[w], f[w-w[i]] + v[i]`

**Realize**

for (int i = 0; I <= W; i + +) { f[w] = 0;} for (int i = 0; I <= n; i + +) {for (int w = w[i]; w <= W; w + +) { //here recursion from left to right!! Because it is necessary to update the previous value to affect subsequent values f[w] = max{f[w], F[w-w[i]] + v[i]};} }

**Analysis of Complexity**

After space optimization, the space complexity is O (W) and the time complexity is O (n*w)

**contrast 01 backpack and full backpack**

Can use a one-dimensional array to reduce the complexity of the space, when using a one-dimensional array, the W order of the 01 backpack is from backward forward (w ~ w-w[i]), and the full backpack is the former (W-w[i] ~ w).

**three, multiple knapsack problem**
n items, the weight value of the article I is w[i], the value of v[i], and the first item I have c[i]. The load-bearing w of the backpack, the maximum value of the total value of the item that can be put in the backpack.

**Analysis**

Modeled after 01 backpacks and a complete backpack, you can get a recursive formula`f[i][w] = max{f[i-1][w - k*w[i]] + k*v[i] | v属于[0, min(c[i], w/w[i])]`

.

Similar to a complete backpack, is it possible to optimize into one-dimensional recursive form in the same way? The answer is no. Because assuming a large w, w-w[i] is also very large cause the weight of the first I items can not be obtained w-w[i], then we will f[w-w[i]] set to 0, and f[w] = Max{f[w], F[w-w[i]] + v[i]} will become max{f[w], v[i ]}, obviously greater than 0, does not conform to the actual.

OK**to treat the c[i of item I as a different kind of item**, but they have the same weight and value, which translates into a 01 knapsack problem, from ∑< Span id= "mathjax-span-4304" class= "Mrow" >n1c[ i kinds of items, each with only one piece, choose the total weight does not exceed W's item combination, make the value and maximum. At this time the complexity is O (W*∑n 1c [i ) &NBSP;

further optimization, consider a theorem

Given a positive integer n, you can use 1, 2, ... 2^ (k-1), N-2^k + 1 These numbers (approximately log (n)) represent any of the integers in [1,n], where K is the largest positive integer that makes N-2^k + 1 > 0

That is, binary decomposition:

Using this theorem, C[i] (w[i), value of v[i], the article I decomposition to {weight, value} = {W[i], V[i]}, {2*w[i], 2*v[i]}, ... {2^ (k-1) *w[i], 2^ (k-1) *v[i]},{(C[i]-2^k + 1) *w[i], (C[i]-2^k + 1)*V[i]}*A series of items, then converted to 01 knapsack problem.**Note that if there is a new converted {W[k], V[k]} is the same as the original item {W[J], v[j]}, they cannot be merged. **

At this point the time complexity is O (w* (∑n1loG2(c[i]) )。

**Implement**

int weight[max];int value[max];void Expand (int w, int v, int n, int& index) { int k = 1; do{ Weight[index] = k*w; Value[index + +] = k*v; k*=2; } while (K*2 < n); Weight[index] = (n-k + 1) *w; value[index++] = (n-k + 1) *v;}

**iv. mixed knapsack problem**
Mixed backpack The problem is that there are some items in n items that can only be selected or not selected, some items are optional, and some items are limited in number. Under the limit of load bearing w of backpack, the maximum value of the sum of value can be obtained.

The solution is to convert the multi-pack to 01 backpacks and then solve the mix of 01 backpacks and complete backpacks.

for (int i = 1; I <= n; i + +) { if (item i is 01 backpack item) {for (int w = w; w >= W[i]; W--) { f[w] = max{f[w], f[w-w[ I]] + v[i]}; } } else if (item I is a complete backpack item) {for (int w = w[i]; w <= W; w + +) { f[w] = max{f[w], F[w-w[i]] + v[i]};} }

**backpack problem with five or two-dimensional fees**
n items, each item I have two different space consumption, the choice of this item must pay both costs. For each price there is a maximum value to pay (backpack capacity), ask how to select items to make the total value and maximum.

**Analysis**

is no different from one-dimensional constraints, but adds a dimension to the state representation,

F[I][W1][W2] = Max{f[i-1][w], F[i-1][w1-w1[i]][w2-w2[i] + v[i]}, after using space optimization for F[W1][W2] = max{f[w1][w2], f[w1-w1[i]][w2-w2 [i]] + v[i]}, at the same time recursion w1,w2 from the back forward.

**Six, the knapsack problem of the group**
There are n items and a backpack with a capacity of V. The cost of article I is CI, the value is WI. These items are divided into K-groups, each of which conflicts with each other, with a maximum of one item selected. The solution of which items are loaded into the backpack allows the sum of the costs of these items to be no more than the backpack capacity and the maximum value.

**Analysis**

This problem becomes a group of items with a number of strategies: choose one of the groups or not. In other words, f [k, V] indicates the maximum weight that can be obtained by the cost of the first K-Group items:

For k = 1 to K//Set for w = w to 0//load bearing for item I in Group K// Group per item f[w] = max{f[w], F[w-ci] + Wi }

**vii. problems related to knapsack problem**
**7.1 Output Select item scheme**
If you need to not only ask for the maximum value of your backpack, you will also need to ask for the collection of items you have selected in your backpack. You also need to maintain another array g[i][w], if f[i][w] = = F[i-1][w] Indicates that the item I is not selected, then g[i][w] = 0; if f[i][w] = F[i-1[w-w[i]] + v[i), then the item of article I is selected, then G[i ][W] = 1 so that the G array is calculated by the way when solving the F-array.

int i = n, w = w;while (i >= 1) { if (g[i][w] = = 0) {Article I item }else{Selected article I item w = w-w[i] }
i--;}

**7.2 Optimal scheme for minimum output dictionary order**
Dictionary order minimum refers to 1 ... The selection scheme of the n items is arranged in order to minimize the number of dictionaries. In general, it is necessary to pay attention to the strategy when transferring the best scheme with the smallest dictionary order. Sub-problem definition to modify: If there is an option 1 of the best solution, then the answer must contain item 1, the original problem is converted to a backpack capacity of W-C1, 2 items .... The sub-problem of N. Conversely, if the answer does not include item 1, the conversion to backpack capacity is still W, item 2 .... The sub-problem of N.

F[I][W] Indicates the maximum value that can be obtained from the item I,I+1...N by selecting a number of items with a total weight not exceeding W. Then there is a recursive formula: `f[i-1][w] = max{f[i][w], f[i][w-w[i-1]]}`

if f[i][w] = = F[i][w-w[i-1]], then select Article I item. This way, when the recursion is complete, the item with the smaller number is recorded, and the same excellent dictionary-ordered scheme is "overwritten".

**7.3 Total number of best practices**
G[0][0] = 1for (int i = 1; I <= N; i + +) {for (int w = 0; w <= W; w + +) { f[i][w] = max{f[i-1][w], f[i-1][w-w[i ]]}; G[I][W] = 0; if (f[i][w] = = F[i-1][w]) { g[i][w] + = G[i-1][w]; } if (f[i][w] = = F[i-1][w-w[i]] + v[i]) { //may choose not to select item I to obtain the same result, so that the total number of schemes to add g[i][w] + = G[i-1][w-w[i]; } }

**7.4 Finding the K-optimal solution**
For solving the problem of suboptimal solution and K-class, if the corresponding optimal solution problem can write the state transfer equation and solve it with the dynamic programming, then the second optimal solution can often be solved by the same complexity, and the first K solution is more than one coefficient K for the complexity of solving the optimal solution.

The basic idea is that each state is represented as an ordered queue, transforming the max/min in the state transition equation into a merge of ordered queues.

Use f[i][w][k] to indicate that the items in the former I are selected in the total weight of not more than W, the value obtained and the value of the K large, you can launch

F[I][W][K] = KTH_OF_{F[I-1][W][1...K] + F[I-1][W-W[I]][1...K] + v[i]}

**in an ordered array of two sizes K, select the number of K-large numbers common to all the numbers in two arrays. You can use merge sort. **

for (int i = 1; I <= n; i + +) { for (int w = w[i]; w <= W; w + +) { int t = 0, n1 = 0, N2 = 0; while (T < k) { if (F[i-1][w][n1] > F[I-1][W-W[I]][N2] + v[i]) { f[i][w][k] = f[i-1][w][n1++]; } else{ k_th_q = 2; F[i][w][k] = f[i-1][w-w[i]][n2 +] + v[i]; } T + +;}}} Time Complexity of O (nWk);

**Reference**
"Backpack Ninth Lecture"

Dynamic planning--knapsack problem