Features of the DP problem:
- Replay Problem
- Optimum subset exists
The knapsack problem is a classic DP problem, and the 0/1 knapsack problem is the simplest case.
0/1 means that each item has only one, either in a backpack or not.
Problem definition:
There are n items in the backpack with a capacity of W, and the weight of the I item is W (I ),
The value is V (I). The question is how to put it in order to obtain the maximum value without exceeding the backpack capacity.
Algorithm Description:
We need to use recursive thinking to define a (I, j) as the case where the capacity of the previous item is J.
For the maximum value, a (0, j) = 0, a (I, 0) = 0 (I <= N and j <= W ).
If W (I)> J, it indicates that the I-th item cannot be placed in the backpack, and the value remains unchanged. Therefore, a (I, j) = a (I-1, J );
If W (I) <j indicates that the I-th item can be imported into the backpack, either
Do not put, if you choose not to put, the value remains unchanged, a (I, j) = a (I-1, J); if you choose to put,
A (I, j) = V (I) + a (I-1, J-W (I), whether to put or not, the maximum values of the two options are required.
It can be expressed:
Code
Version 1:
Def B (W, V, I, j): If I = 0: If W [I] <= J: Return V [I] else: return 0 without_ I = B (W, V, I-1, J) If W [I]> J: Return without_ I else: with_ I = V [I] + B (W, v, I-1, J-W [I]) return max (without_ I, with_ I) If _ name _ = "_ main __": W = [2, 3, 4, 5, 6] V = [1, 4, 3, 6, 8] I = Len (W) -1 J = 12 print B (W, V, I, j)
The implementation of version 1 can solve the problem according to the algorithm idea, but the time complexity is exponential.
It takes a long time to calculate the value. This is also a problem with recursive algorithms.
Memorization technology, that is, the method for storing the median value, records the previously calculated sub-problem values. No
Use the re-calculation, and use it directly.
Version 2:
M = {} def fastb (W, V, I, j): Global M try: Return M [(I, j)] random t keyerror: If I = 0: if W [I] <= J: M [(I, j)] = V [I] Return V [I] else: M [(I, j)] = 0 return 0 without_ I = fastb (W, V, I-1, J) If W [I]> J: M [(I, j)] = without_ I return without_ I else: with_ I = V [I] + fastb (W, V, I-1, J-W [I]) RES = max (without_ I, with_ I) m [(I, j)] = res return res if _ name _ = "_ main _": W = [2, 3, 4, 5, 6] V = [1, 4, 3, 6, 8] I = Len (w)-1 J = 12 print fastsub (M, W, I, j)
Version 2: Because variable B is added to store the median, the actual running speed is greatly improved, and the time complexity is close
Linear, with space for time.
Additional questions:
When finding the maximum value, you must return the optimal list of specific items.
Algorithm Description:
To solve this problem, use the M dictionary obtained in the previous problem and calculate it from the last result. The value range is [n-]. When M [(I, j)]> M [(I-1, J)], put the item I into the optimal list, then J = J-W (I), continue forward ratio, after comparison, finally, we decided whether to add 0th items to the backpack. When the weight of all items in the optimal list plus the weight of 0th items does not exceed the capacity limit, we added 0th items to the optimal list, otherwise, do not join
Code:
Def findmaxsub (M, W, I, j): res = [] maxweight = J sum = 0 for index in range (I, 0,-1 ): if M [(index, j)]> M [(index-1, J)]: Res. append (INDEX) J = J-W [Index] For item in Res: Sum = sum + W [item] If maxweight-sum> = W [0]: Res. append (0) return res