----- Edit by ZhuSenlin HDU
The full backpack is in NTypeSeveral items (the same item can be selected multiple times) are selected and placed in a backpack with a space of V.TypeThe size of an item is C1, C2 ,..., Cn, corresponding value: W1, W2 ,..., Wn. Solve how to install items to maximize the total value of items in the backpack.
Dynamic Planning (DP ):
1) subproblem definition: F [I] [j] indicates the first ITypeThe maximum value that can be obtained by selecting items in an item and placing them in a backpack with the free space j.
2) According toTypeHow many items are placed for decision-making
(2-1)
Where F [I-1] [j-K * C [I] + K * W [I] represents the front I-1TypeSelect several items in the item and place them in the backpack with the remaining space j-K * C [I ].TypeItem;
Set itemQuantityIs N, the backpack capacity is V, the ITypeItem size: C [I], ITypeThe value of an item is W [I].
Similar to the 01 backpack, The NV state F [I] [j] must be obtained for the full backpack. However, if a backpack is used for F [I] [j], 0 is required for k ,..., J/C [I] calculates the maximum F [I] [j] value, and the time consumed is j/C [I]. The total time complexity is O (NV Σ (j/C [I]).
The pseudocode is written as follows:
F[0][] ← {0} F[][0] ← {0} for i←1 to N do for j←1 to V do for k←0 to j/C[i] if(j >= k*C[i]) then F[i][k] ← max(F[i][k],F[i-1][j-k*C[i]]+k*W[i]) return F[N][V]
The preceding pseudo-code array is based on a 1 index, that is, the index of the first item is 1.Space complexity O (VN), time complexity O (NV Σ (j/C [I])
Simple optimization:
If the two items meet the requirements of C [I] ≤ C [j] & W [I] ≥ W [j], filter the items in the j category directly. Because the I-th item is cheaper than the j-th item, replace j with I to get at least no worse solution.
This screening process is as follows: first, find out the items larger than the backpack and directly screen out a portion (or either of them cannot) of the complexity O (N ). Sort the remaining items by counting and sorting, filter out the items with the same volume and the greatest value, and screen out the remaining items (this may not be part of the screen) complexity O (V ). The time complexity of the entire process is O (N + V)
Convert to 01 backpack:
Because the same item can be selected multiple times, you can select a maximum of items with the same value as V/C [I] For the I item, and then convert it to the 01 backpack. The time complexity of the entire process is not reduced. If the I-th item is split into items with a volume of C [I] × 2 K value W [I] × 2 K, C [I] × 2 k ≤ V. When the state F [I] [j] is obtained, the complexity changes to O (log2 (V/C [I]). The entire time complexity is changed to O (NVlog2 (V/C [I]).
Time complexity is optimized to O (NV)
Change the original algorithm's DP idea.
Setting F [I] [j] indicates the maximum value of choosing a number of items from the first I items and placing them in a backpack with a size of j. So for the emergence of type I items, we do not put the type I items into a backpack for decision-making. If not, F [I] [j] = F [I-1] [j]; if it is determined to be placed, at least one type of I item should appear in the backpack, therefore, F [I] [j] should contain at least one item, that is, F [I] [j] = F [I] [j-C [I] + W [I]. Why is it F [I] [j-C [I] + W [I]? Because F [I] [j-C [I] may have type I or no type I item. We need to ensure that F [I] [j] has at least one I item, so we need to reserve space for C [I] to store one I item.
The state equation is:
(2-2)
Pseudocode:
F[0][] ← {0} F[][0] ← {0} for i←1 to N do for j←1 to V F[i][j] ← F[i-1][j] if(j >= C[i]) then F[i][j] ← max(F[i][j],F[i][j-C[i]]+ W[i]) return F[N][V]
The method for finding the items in a specific backpack is similar to that of the 01 backpack. From F [N] [V] to F [0] [0], set I = N, j = V. If F [I] [j] = F [I] [j-C [I] + W [I] indicates that the package contains the I-th item, j-= C [I] at the same time. The problem with a full backpack is different from that with a self-reduction I and A 01 backpack, 01 if the backpack is not the same as F [I] [j] and F [I-1] [j-C [I] + W [I], I will be reduced by 1, because 01 the I-th item of the backpack is either put or not put, whether put or not it has been traversed, we need to continue traversing down and the full backpack will only auto-subtract 1 if F [I] [j] is equal to F [I-1] [j. Because F [I] [j] = F [I-1] [j] indicates that the backpack does not contain I, that is to say, for all the items whose capacity is j are put in the former I-1 to maximize the value, or simply put, the I-th item in the first I item is not cost-effective and is directly filtered out.
The pseudocode for printing items in a backpack is as follows:
i←N j←V while(i>0 && j>0) do if(F[i][j]=F[i][j-C[i]]+W[i]) then Print W[i] j←j-C[i] else i←i-1
Like a 01 backpack, you can also use a two-dimensional array Path [] [] to mark items in the backpack. At the beginning, Path [N] [V] is initialized to 0, when F [I] [j] = F [I] [j-C [I] + W [I], Path [I] [j] is set to 1. Finally, we can obtain the items in the backpack from Path [N + 1] [V + 1] to Path [0] [0. Path [0] [] and Path [] [0] are boundaries. Similarly, when Path [] [] = 1 is printed, W [I]; Path [] [] = 0 is printed.
The pseudocode for adding path information is as follows:
F[0][] ← {0} F[][0] ← {0} Path[][] ← 0 for i←1 to N do for k←1 to V F[i][k] ← F[i-1][k] if(k >= C[i] && F[i][k] < F[i][k-C[i]]+W[i]) then F[i][k] ← F[i][k-C[i]]+W[i] Path[i][k] ← 1 return F[N][V] and Path[][]
The pseudocode for printing items in a backpack is as follows:
i←N j←V while(i>0 && j>0) do if(Path[i][j]=1) then Print W[i] j←j-C[i] else i←i-1
The optimized space complexity is O (V)
Similar to the 01 backpack, a full backpack can use a one-dimensional array to store data. The algorithm style is very similar to that of the 01 backpack. The only difference is that the V-time duration is in the forward order, while the 01 backpack is in the reverse order. 01 in the backpack, the reverse order is because F [I] [] is only related to F [I-1] [], andPartsThe addition of items does not affect the F [I-1] [] status. The full backpack considers the ITypeIf the first item appears, it will inevitably affect the status of the item that has not yet appeared. That is to say, there may be an optimal solution when there is no type I item, and now the type I item appears, and its addition may obtain a better solution, so the previous status needs to be changed, so it needs to be in the forward order.
The state equation is:
(2-3)
The pseudocode is as follows:
F[] = {0} for i←1 to N do for k←C[i] to V F[k] ← max(F[k],F[k-C[i]]+W[i]) return F[V]
The method for finding the items in a specific backpack is the same as the space complexity above is the O (NV) algorithm. A Path [] [] is used to record the backpack information. However, if F [I] = F [I-C [I] + W [I], set Path to 1.
The pseudocode is as follows:
F[0][] = {0} F[][0] = {0} Path[][] ← 0 for i←1 to N do for k←C[i] to V if(F[i] < F[k-C[i]]+W[i]) then F[i] ← F[k-C[i]]+W[i] Path[i][k] ← 1 return F[N][V] and Path[][]
The pseudocode of the print path is the same as that of the pseudo code when the preceding space is not compressed, and will not be overwritten here.
For example, table 2-1 is a data table about a backpack problem. If the size of the backpack is set to 10, the corresponding F [I] [J] can be obtained based on the above solution, as shown in Table 2-2, the maximum value is f [6] [10].
Table 2-1 knapsack problem data table
Item No. I |
1 |
2 |
3 |
4 |
5 |
6 |
Volume C |
3 |
2 |
5 |
1 |
6 |
4 |
Value W |
6 |
5 |
10 |
2 |
16 |
8 |
Table 2-2 maximum value of items selected by I in a backpack with J Space
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
6 |
6 |
6 |
12 |
12 |
12 |
18 |
18 |
2 |
0 |
0 |
5 |
6 |
10 |
11 |
15 |
16 |
20 |
21 |
25 |
3 |
0 |
0 |
5 |
6 |
10 |
11 |
15 |
16 |
20 |
21 |
25 |
4 |
0 |
2 |
5 |
7 |
10 |
12 |
15 |
17 |
20 |
22 |
25 |
5 |
0 |
2 |
5 |
7 |
10 |
12 |
16 |
18 |
21 |
23 |
26 |
6 |
0 |
2 |
5 |
7 |
10 |
12 |
16 |
18 |
21 |
23 |
26 |
The following is a test code for the two methods described in Table 2-1:
# Include <iostream> # include <cstring> # include "createarray. H" // This header file is used to create and destroy two-dimensional arrays. You can implement using namespace STD by yourself;
// Time complexity O (VN) and space complexity O (VN)
Int package02 (INT weight [], int value [], int nlen, int ncapacity) {int ** table = NULL; int ** Path = NULL; createtwodimarray (table, nlen + 1, ncapacity + 1); // create a two-dimensional array createtwodimarray (path, nlen + 1, ncapacity + 1); // create a two-dimensional array for (INT I = 1; I <= nlen; I ++) {for (Int J = 1; j <= ncapacity; j ++) {table [I] [J] = table [I-1] [J]; if (j> = weight [I-1] & table [I] [J] <Table [I] [J-weight [I-1] + value [I-1]) {table [I] [J] = table [I] [J-weight [I-1] + value [I-1]; path [I] [J] = 1 ;}}} int I = nlen, j = ncapacity; while (I> 0 & J> 0) {If (path [I] [J] = 1) {cout <weight [I-1] <"; j-= weight [I-1];} elseI --;} cout <Endl; int nret = table [nlen] [ncapacity]; destroytwodimarray (table, nlen + 1); // destroy the two-dimensional array destroytwodimarray (path, nlen + 1 ); // destroy the two-dimensional array return nret ;}
// Time complexity O (VN). The path space complexity is O (V), and the path space complexity is O (VN)
Int Package02_Compress (int Weight [], int Value [], int nLen, int nCapacity) {int * Table = new int [nCapacity + 1]; memset (Table, 0, (nCapacity + 1) * sizeof (int); int ** Path = NULL; CreateTwoDimArray (Path, nLen + 1, nCapacity + 1 ); // create a two-dimensional array for (int I = 0; I <nLen; I ++) {for (int j = Weight [I]; j <= nCapacity; j ++) {if (Table [j] <Table [j-Weight [I] + Value [I]) {Table [j] = Table [j-Weight [I] + Value [I]; Path [I + 1] [j] = 1 ;}}} int I = nLen, j = nCapacity; while (I> 0 & j> 0) {if (Path [I] [j] = 1) {cout <Weight [I-1] <"; j-= Weight [I-1];} elsei --;} cout <endl; int nRet = Table [nCapacity]; destroyTwoDimArray (Path, nLen + 1); // destroy the two-dimensional array delete [] Table; return nRet ;}
Test code:
int main(){int Weight[] = {3,2,5,1,6,4};int Value[] = {6,5,10,2,16,8};int nCapacity = 10;cout << Package02(Weight,Value,sizeof(Weight)/sizeof(int),nCapacity) << endl;cout << Package02_Compress(Weight,Value,sizeof(Weight)/sizeof(int),nCapacity) << endl;return 0;}
For some content in this article, refer to "backpack 9 lecture"