The algorithm of 0-1 knapsack problem is solved by Priority Queue Branch-bound method:
1. The branch-and-bound method often searches for the solution space Tree of the problem in the way of breadth first or least cost first (maximum benefit priority), and the solution space tree for the 0-1 knapsack problem is a subset tree.
2. In the branch-bound method, there is a Slipknot point table, each Slipknot point in the Slipknot Point table has only one chance to become an extension node, once it becomes an extension node, all son nodes are generated at once, and in these sons nodes, the son node that leads to the non-optimal solution or causes the suboptimal solutions is discarded and the remaining son nodes are added For each Slipknot point in the 0-1 knapsack problem, there are only two sons nodes, respectively, indicating the selection of the item I and the House of the item I; In judging whether the son node can be added to the Slipknot point table, there are two functions to be satisfied, the first is called the constraint function, determine whether the knapsack capacity constraints, the second known as the Limit function, Whether the optimal solution is possible.
3. In order to find the solution of the 0-1 knapsack problem as soon as possible, each time the next Slipknot point is chosen as the extension node, it is the next node that is most likely to find the optimal solution in the current situation. Therefore, each time you select an extension node: In the current case, select the upper bound of the Slipknot point in the Slipknot Point table Uprofit (calculated through the bounds function bound) The largest Slipknot point becomes the current expansion node. This process persists until you find the desired solution or the Slipknot point table is empty. This process reflects the "maximum benefit priority" approach to the branch-bound method.
4. In order to select the Slipknot point with the largest upper bound uprofit in the Slipknot Point table, the priority queue is implemented on the Slipknot point table.
5. Through the 3rd above, the optimal value of the 0-1 knapsack problem can be obtained. In order to find out the optimal solution of the 0-1 knapsack problem, for each Slipknot point in the Slipknot Point table, the tree node needs to reflect the parent of the node and whether there is a left child (there is a left child to indicate that the item I was selected, no left child indicated that the item I had gone). Therefore, a subset tree can be constructed, and the optimal solution is the path from the root to the leaf node, and all nodes of the layer I of the subset tree are the trade-offs of item I under different circumstances. The order of constructing the optimal solution is the process from the leaf node to the root node.
From the above algorithm thought, the problem that must be solved is drawn:
1. Priority queue-type Slipknot point table
2. Subset tree corresponding to the Slipknot point table
function functions involved in the algorithm:
1. Create a maximum heap, initialize the maximum heap, insert an element in the largest heap, and remove the largest element in the largest heap
2. Main function knapsack for solving 0-1 knapsack problem
3. Insert a node function into the subset tree and the largest heap Addlivenode
4. Calculate the upper bound function of the node value bound, in order to be convenient, it is necessary to sort items by unit value
5. Responsible for solving the problem of 0-1 knapsack optimal value and the optimal solution function Maxknapsack
The classes involved in the algorithm:
1. Tree node class for constructing a subset tree to calculate the optimal solution
2. Heap node class, used to define the type of heap elements to facilitate the use of Maxknapsack functions
3. Maximum heap class for implementing a priority queue
4. Item class, for storing the item number and the unit weight value of the item
5. Solve the 0-1 knapsack problem main class
The following is the specific code:
#include "stdafx.h" #include <iostream>using namespace std; typedef int TYPEW;TYPEDEF int typep;//Item class Object{friend TYPEP knapsack (Typew *, Typep *, Typew, int, int *);p ublic:in T operator <= (Object a) Const{return (d >= A.D); Private:int ID; Item number float D; Unit weight Value};//tree Node classes class Bbnode{friend class Knap;friend Typep knapsack (Typew *, Typep *, Typew, int, int *);p Rivate:bbnode * Parent Pointer to parent node int lchild; If the left son node takes 1, that means the item has been loaded into the Backpack};//heap node class Heapnode{friend class Knap;friend class Maxheap;public:operator Typep () const{ return uprofit;}; Private:typep Uprofit,//node value upper bound profit; The corresponding value of the node is Typew weight; The corresponding weight of the junction int level; The Slipknot points in the subset tree are located in the layer ordinal bbnode *elemptr; Pointer to the Slipknot point in the subset tree corresponding node};//max heap class maxheap{public:maxheap (int maxelem) {Heapelem = new heapnode* [maxelem+1];// The subscript is 0 reserved capacity = Maxelem;size = 0;} void Insertmax (Heapnode *newnode); Heapnode Deletemax (heapnode* &n);p rivate:int capacity; int size; Heapnode **heapelem; };//0-1 knapsack problem of the main class KNAP{//KNAPSAfunction of CK main function: Solve initialization, solve optimal value and optimal solution, reclaim memory friend Typep knapsack (Typew *, Typep *, Typew, int, int *);p ublic:typep maxknapsack (); Private:maxheap *h;//bound Auxiliary maxknapsack function: compute the upper bound of the node value TYPEP Bound (int i);// Addlivenode Auxiliary maxknapsack function: insert Slipknot points into the subset tree and Priority queue void Addlivenode (Typep up, Typep CP, Typew CW, int CH, int. level); Bbnode *e; Pointer to extension node Typew C; backpack capacity int n; Total number of items Typew *w; Item weight Array (descending in unit weight value) Typep *p; Array of item values (descending in unit weight value) Typew CW; Current pack weight TYPEP CP; Current pack value int *bestx; Optimal solution};void Maxheap::insertmax (Heapnode *newnode) {///extreme case not considered, such as heap capacity is full and so on int i = 1;for (i = ++size; I/2 > 0 && He Apelem[i/2]->uprofit < newnode->uprofit; I/= 2) {heapelem[i] = HEAPELEM[I/2];} Heapelem[i] = NewNode;} Heapnode maxheap::D eletemax (Heapnode *&n) {///extreme case not considered if (size >0) {N = heapelem[1];//adjusts int i = 1;while starting from the top of the heap (I < Size) {if ((i*2 + 1) <= size) && heapelem[i*2]->uprofit > Heapelem[i*2 +1]->uprofit) {Heapelem[i] = Heapelem[i*2];i = i*2;} else{if (i*2 <= size) {Heapelem[i] = Heapelem[i*2];i = i* * *;} Elsebreak;}} if (i < size) Heapelem[i] = heapelem[size];} Size--;return *n;} Typep Knap::maxknapsack () {H = new Maxheap (+), bestx = new int [n+1];//initialization, preparing for processing the first layer in the subset tree, item I is in the sub-layer of the subset I int i = 1;//Generating a subset tree The node of the first layer in E = 0; Set the first extension point to NULL, which is the parent node of item 1, CW = 0;CP = 0; Typep BESTP = 0; Current optimal value Typep up = Bound (1); Select the value upper bound after item 1//When the left son node is selected, the upper bound constraint up does not care, weight constraint wt needs to be considered. Because the upper bound constraint is the same as the parent node. When choosing the right son node, the upper bound constraint up needs to be considered, and the weight constraint does not need to be considered. Because the parent node and the node weigh the same. while (i! = n+1) {//Check the left son node of the current extension node Typew WT = CW + w[i];//////////////////////////////////////////////////// + P[i] > BESTP) BESTP = CP + p[i]; Addlivenode (UP, CP + P[i], CW + w[i], 1, i);} Check the right son node of the current extension node up = Bound (i + 1); The value upper bound if the item I is not selected if (up >= BESTP) Addlivenode (UP, CP, CW, 0, I);//Select the node with the highest upper value from the priority queue to become the expansion node heapnode* N; H->deletemax (N); E = N->ELEMPTR;CW = N->WEIGHT;CP = N->profit;up = N->uprofit;i = N->level + 1; Prepare to generate a subset tree node of the n.level+1 layer}//from a leaf node in the subset tree to construct the current optimal solution for (int i = n; i > 0; i--) {Bestx[i] = e->lchild; E = e->parent;} return CP;} Typep KnAp::bound (int i) {Typew cleft = C-CW; Typep B = cp;while (i<=n && w[i] <= cleft) {cleft-= w[i];b + = p[i];i++;} if (i<=n) b + = p[i]/w[i] * Cleft;return b;} void Knap::addlivenode (Typep up, Typep CP, Typew CW, int CH, int. level) {Bbnode *b=new bbnode; b->parent=e; b->lchild=ch; Heapnode *n = new Heapnode; n->uprofit=up; n->profit=cp; n->weight=cw; n->level=level; n->elemptr=b; H->insertmax (N); }//knapsack returns the maximum value, the optimal value is saved in Bestxtypep knapsack (Typew *w, Typep *p, Typew c, int n, int *bestx) {//array w, p and bestx the element labeled 0 remains unused// Initialize Typew W = 0; Typep P = 0;object *q = new Object[n];for (int i =1; i<=n; i++) {q[i-1].id = i; Q[I-1].D = 1.0*p[i]/w[i]; P + = P[i]; W + = W[i];} The total weight of all items is less than or equal to the backpack capacity CIF (W <= c) {for (int i =1; i<=n; i++) {bestx[i] = p[i];} return P;} The total weight of all items is greater than the backpack capacity C, there is the best package scheme//sort (q,n); The item is sorted in descending order of unit weight value//using a simple bubble sort for (int i = 1; i<n; i++) for (int j = 1; j<= n-i; j + +) { if (Q[j-1].d < Q[J].D) {Object temp = q[j-1]; q[J-1] = Q[j]; Q[J] = temp;}} Knap K; K.P = new Typep [n+1]; K.W = new Typew [n+1];for (int i = 1; i<=n; i++) {K.p[i] = p[q[i-1].id];//(in descending order of unit weight value) k.w[i] = w[q[i-1].id];//(in descending order of unit weight value) Sort)}K.CP = 0; K.CW = 0; K.C = C; K.N = n; Typep BESTP = K.maxknapsack (); for (int i = 1; i<=n; i++) {bestx[q[i-1].id] = k.bestx[i];} Delete [] q;delete [] k.w;delete [] k.p;delete [] k.bestx;delete [] K.h;return BESTP;} int _tmain (int argc, _tchar* argv[]) {const int N = 4; Typew c=8; Backpack capacity int bestx[n+1]; optimal solution int BESTP; The best value//need to be explained is that the first element of the array p[] and w[] here is-1, this is because I am in the process//both from the array elements of the beginning of 1, and we know that the first element in the array is the No. 0 element, so I use 1 here to fill in the Typep p[]={- 1,6,4,7,4};//Item Value Typew w[]={-1,2,3,5,2};//Item Weight BESTP = knapsack (W, p, C, N, BESTX);cout<< "Total number of items N =" << n&l t;< ", backpack capacity c =" << c<<endl;for (int i = 1; I <= N; i++) {if (I ==1) cout<< "weight array:"; Cout<<w[i];if (i! = N) cout<< ","; Elsecout<<endl;} for (int i = 1; I <= N; i++) {if (I ==1) cout<< "value array:"; Cout<<p[i];if (i! = N) cout<< ","; Elsecout<<endl;} for (int i = 1; I <= N; i++) {if (I ==1) cout<< "If selected:"; Cout<<bestx[i];if (i! = N) cout<< ","; elsecout< ; <endl;} cout<< "Backpack Best Value:" <<bestp<<endl;system ("pause"); return 0;}
Running results such as:
Solving 0-1 knapsack problem with priority queue Branch-and-gauge method