Knapsack Problem-"01 backpack" explanation and implementation (including solving specific items in the backpack)

Source: Internet
Author: User

----- Edit by zhusenlin HDU

01 A backpack is a backpack with several items taken out of M and placed in W space. The size of each item is C1, C2 ,..., Cn, corresponding value: W1, W2 ,..., Wn. Solving these items into a backpack can maximize the total value.

Dynamic Planning (DP ):

1) subproblem definition: F [I] [j] indicates the maximum value that can be obtained when several items are selected from the first I items are placed in a backpack with the free space j.

2) make a decision based on whether to place or not to place the I-th item

(1-1)

Among them, F [I-1] [j] indicates the maximum value of the items selected from the front I-1 items in the left space j in the backpack;

F [I-1] [j-C [I] + W [I] indicates that several items selected from the items in the front I-1 are placed into the backpack with the remaining space j-C [I] the maximum value that can be obtained plus the value of the I-item.

The status F [I] [j] when traversing the I-th item based on whether the I-th item is put or not.

Set the number of items to N, the size of the backpack to V, the size of the I item to C [I], and the value of the I item to W [I].

The pseudocode is written as follows:

     F[0][] ← {0}     F[][0] ← {0}     for i←1 to N         do for k←1 to V             F[i][k] ← F[i-1][k]             if(k >= C[i])                 then F[i][k] ← max(F[i][k],F[i-1][k-C[i]]+W[i])     return F[N][V]

The preceding pseudo-code array is based on the 1 index and the first item index is 1.Time and space complexity are O (VN)

For example, table 1-1 is a backpack problem data table with a backpack capacity of 10. According to the above solution, the corresponding F [I] [j] can be obtained, as shown in table 1-2, the maximum value is F [6] [10].

Table 1-1 knapsack problem data table

Item No. I 1 2 3 4 5 6
Volume C 2 3 1 4 6 5
Value W 5 6 5 1 19 7

 

Table 1-2 the largest value table obtained when I selected several items and placed them 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 5 5 5 5 5 5 5 5 5
2 0 5 6 6 11 11 11 11 11 11 11
3 0 5 5 10 11 11 16 16 16 16 16
4 0 5 5 10 11 11 16 16 16 16 17
5 0 5 5 10 11 11 19 24 24 29 30
6 0 5 5 10 11 11 19 24 24 29 30

 

Many articles only find out the maximum value of a backpack, and do not find out which items are selected. I encountered many similar problems before I learned about my backpack. At that time, I only obtained the greatest value or the largest sum, and I was helpless in terms of specific items or paths. I will share with you the details.

The maximum value table obtained based on the algorithm actually contains location information, from F [N] [V] to F [0] [0], where I = N, j = V, if F [I] [j] = F [I-1] [j-C [I] + W [I] indicates that the package contains I items, j-= C [I], whether F [I] [j] and F [I-1] [j-C [I] + W [I] are not equal, I is reduced by 1, because the I-th item of the 01 backpack is either put or not put, whether put or not it has already been traversed, You need to continue traversing.

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-1][j-C[i]]+W[i])             then Print W[i]                  j←j-C[i]         i←i-1

Of course, you can also define a two-dimensional array Path [N] [V] to store information about the items in the backpack. At the beginning, Path [N] [V] is initialized to 0, when F [I] [j] = F [I-1] [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.

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-1][k-C[i]]+W[i])                 then F[i][k] ← F[i-1][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]         i←i-1

When both the time and space complexity are O (NV, the method of using Path [] [] is obviously more effective than printing by F [I] [j] = F [I-1] [j-C [I] + W [I ]. space-consuming items, path [] [] requires extra space O (NV), but the total space complexity remains unchanged at O (NV ). But the O (V) but cannot use the relational F [j] = F [j-C [I] + W [I], rather than using Path.

 

Next, we will consider how to compress the space to reduce the space complexity.

The time complexity is O (VN), and the space complexity is O (V)

 

Observation of pseudocode can also be found that F [I] [j] is only related to F [I-1] [j] and F [I-1] [j-C [I, that is, it is only related to the I-1 time state, so we only need to use a one-dimensional array F [] to save the state F [] When the I-1. Assume that F [] of the I-1 moment is {a0, a1, a2 ,..., Av}, the k number in F [] of the hard I time should be max (ak, ak-C [I] + W [I]) max (F [k], F [k-C [I] + W [I]). This requires us to traverse V in reverse order, this ensures that F [k-C [I] is the value of the I-1 moment. If forward traversal is performed, F [0], F [1],… before F [k] is obtained. F [K-1] has changed, the memory is not the value of the I-1 time, so that F [k] When Using F [K-C [I] must be the wrong value. Finally, F [V] is the maximum value.

The equation of state for F [j] is as follows:

(1-2)

The pseudocode is as follows:

     F[] ← {0}     for i ← 1 to N         do for k ← V to C[i]             F[k] ← max(F[k],F[k-C[i]]+W[i])     return F[V]

Similarly, how to find the path?

Use the Path [] [] Mark mentioned above to consume space O (NV ). Here, F [j] = F [j-C [I] + W [I] cannot be used to determine whether a one-dimensional array does not provide enough information to find a two-dimensional path.

The pseudocode for adding path information is as follows:

     F[] ← {0}     Path[][]←0     for i←1 to N         do for k←V to C[i]            if(F[k] < F[k-C[i]]+W[i])                 then F[k] ← F[k-C[i]]+W[i]                      Path[i][k] ← 1     return F[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.

 

The following code provides two methods for testing table 1-1: 

# Include <iostream> # include <cstring> # include "createarray. H" // This header file is used to dynamically create and destroy two-dimensional arrays. You can implement using namespace STD by yourself;

// Time complexity O (VN) and space complexity O (VN)

Int package01 (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]; path [I] [J] = 0; if (j> = weight [I-1] & table [I] [J] <Table [I-1] [J-weight [I-1] + value [I-1]) {table [I] [J] = table [I-1] [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];} I --;} 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 package01_compress (INT weight [], int value [], int nlen, int ncapacity) {int * Table = new int [ncapacity + 1]; memset (table, 0, (ncapacity + 1) * sizeof (INT); int ** Path = 0; createtwodimarray (path, nlen + 1, ncapacity + 1 ); // create a two-dimensional array for (INT I = 0; I <nlen; I ++) {for (Int J = ncapacity; j> = weight [I]; j --) {path [I + 1] [J] = 0; 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];} I --;} 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[] = {2,3,1,4,6,5};int Value[] =  {5,6,5,1,19,7};int nCapacity = 10;cout << Package01(Weight,Value,sizeof(Weight)/sizeof(int),nCapacity) << endl;cout << Package01_Compress(Weight,Value,sizeof(Weight)/sizeof(int),nCapacity) << endl;return 0;}

 

For some content in this article, refer to "backpack 9 lecture"

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.