1, problem description :
Given n kinds of goods and a backpack. The weight of item I is WI, its value is VI, the capacity of the backpack is C. Q: How do I choose which items are loaded into my backpack so that the total value of the items loaded into the backpack is greatest?
Formal description: Given C >0, WI >0, vi >0, 1≤i≤n. Required to find an n-ary vector (x1,x2,..., xn,), Xi∈{0,1},∋∑wi xi≤c, and ∑vi XI up to the largest. That is, a special integer programming problem.
2, the principle of optimality :
(Y1,y2,..., yn) is an optimal solution for (3.4.1). Then (Y2,..., yn) is an optimal solution for the following sub-problems:
Proof: The use of the rebuttal method. If not, setting (Z2,z3,..., Zn) is an optimal solution to the sub-problem, and (Y2,y3,..., yn) is not the optimal solution. Obviously there are
∑vizi >∑viyi (i=2,..., N)
and w1y1+∑wizi<= C
So V1y1+∑vizi (i=2,..., N) >∑viyi, (I=1,..., N)
Description (y1,z2, Z3,..., Zn) is a better solution to the (3.4.1) 0-1 knapsack problem, the export (Y1,y2,..., yn) is not the optimal solution of knapsack problem, contradiction.
3. Recurrence Relationship :
Set the sub-problem of the 0-1 knapsack problem
The optimal value is M (i,j), that is, M (i,j) is the backpack capacity of J, can choose the item for the I,i+1,...,n 0-1 knapsack problem optimal value. By the optimal substructure properties of the 0-1 knapsack problem, the recursive formula for calculating m (I,J) can be established:
Note: (3.4.3) This time the backpack capacity is J, can choose the item for I. At this point, after making a decision on XI, the problem is in one of two states:
(1) The remaining capacity of the backpack is J, which has no benefit;
(2) The surplus capacity J-wi, the benefit value increases VI;
Use the recursive C + + code as follows:
#include <iostream>using namespacestd;Const intn=3;Const intw= -;intweights[n+1]={0,Ten, -, -};intvalues[n+1]={0, -, -, -};intv[n+1][w+1]={0};intKnapsack (intIintj) { intvalue; if(v[i][j]<0) { if(j<Weights[i]) {Value=knapsack (I-1, J); } Else{Value=max (Knapsack (i-1, j), Values[i]+knapsack (i1, J-weights[i])); } V[i][j]=value; } returnv[i][j];}intMain () {inti,j; for(i=1; i<=n;i++) for(j=1; j<=w;j++) V[i][j]=-1; cout<<knapsack (3, -) <<Endl; cout<<Endl;}
Do not use recursive C + + code: Simple Modification http://www.cppblog.com/Geek/archive/2009/12/02/102393.html
//3d10-1 Dynamic Planning knapsack problem#include <iostream>using namespacestd;Const intN =4;voidKnapsack (intV[],intW[],intCintNintm[][Ten]);voidTraceback (intm[][Ten],intW[],intCintNintx[]);intMain () {intC=8; intv[]={0,2,1,4,3},w[]={0,1,4,2,3};//Subscript starting from 1 intx[n+1]; intm[Ten][Ten]; cout<<"the weight of items to be loaded are:"<<Endl; for(intI=1; i<=n; i++) {cout<<w[i]<<" "; } cout<<Endl; cout<<"the value of items to be loaded are:"<<Endl; for(intI=1; i<=n; i++) {cout<<v[i]<<" "; } cout<<Endl; Knapsack (V,W,C,N,M); cout<<"the maximum value of a backpack can be:"<<m[1][c]<<Endl; Traceback (M,W,C,N,X); cout<<"the item number under the back package is:"<<Endl; for(intI=1; i<=n; i++) { if(x[i]==1) {cout<<i<<" "; }} cout<<Endl; return 0;}voidKnapsack (intV[],intW[],intCintNintm[][Ten]){ intJmax = min (w[n]-1, c);//backpack remaining capacity upper range [0~w[n]-1] for(intj=0; j<=jmax;j++) {M[n][j]=0; } for(intJ=w[n]; j<=c; J + +)//limit range [W[n]~c]{M[n][j]=V[n]; } for(inti=n-1; I>1; i--) {Jmax= Min (w[i]-1, c); for(intj=0; j<=jmax; J + +)//backpack with different remaining capacity j<=jmax<c{M[i][j]= m[i+1][J];//It didn't produce any benefits . } for(intJ=w[i]; j<=c; J + +)//backpack different remaining capacity J-wi >c{M[i][j]= Max (m[i+1][j],m[i+1][j-w[i]]+v[i]);//Benefit value Growth VI}} m[1][C] = m[2][c]; if(c>=w[1]) {m[1][C] = max (m[1][c],m[2][c-w[1]]+v[1]); }}//x[] Array storage corresponding item 0-1 vector, 0 not pack in Backpack, 1 means pack in backpackvoidTraceback (intm[][Ten],intW[],intCintNintx[]) { for(intI=1; i<n; i++) { if(M[i][c] = = m[i+1][c]) {X[i]=0; } Else{X[i]=1; C-=W[i]; }} X[n]= (M[n][c])?1:0;}
Operation Result:
Algorithm execution process to m[][] filling in and traceback backtracking process:
It is easy to see from the recursion of M (I,J) that the algorithm knapsack requires O (NC) computing time; The Traceback requires O (n) to calculate the time, and the overall algorithm needs O (NC) Calculation time. When the backpack capacity C is large, the algorithm needs more computation time. For example, when c>2^n, the algorithm requires Ω (n2^n) calculation time.
16th Chapter Greedy Algorithm--0/1 knapsack problem