实验报告 分支限界法01背包

合集下载

分支限界法的优先队列方式求解

分支限界法的优先队列方式求解
bestx:bestx[i]=1最优解中有物品i
物品 1 2 3 cp 48 30 30 cw 16 15 15 D cp/cw 3 2 2 H I
B E F
C G
J
K
L
M
N
O
分支限界法的优先队列方式求解0-1背包问题 cw=0 cp=0 up=90
1
cw=16 up=76 cp=48
0
cw=0 up=90 cp=0
A
B E F
C G
D
HIBiblioteka JKLM
N
O
分支限界法的优先队列方式求解 0-1背包问题
中国民航大学 计算机科学与技术学院 刘东楠 1505040
分支限界法的优先队列方式求解0-1背包问题
0-1背包问题:给定n种物品和一背包。物品i的重量是wi,其价值为vi,
背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中的物品的 总价值最大?
解题步骤:
Step1:搜索解空间建立二叉树,从根节点A开始。 Step2:广度优先遍历二叉树,并用极大堆表示活节 点的优先级,选取扩展节点,找出可行解。 Step3:找出最优解。
在算法中,算法首先检查当前扩展 节点的左儿子的可行性。如果左儿 子节点是可行节点,则将它加入到 子集数和活节点优先队列中。当前 扩展节点的右儿子一定是可行节点, 仅当右儿子满足上界约束时才将它 加入子集数和活节点优先队列。 A
-搜索方法不同:
回溯法使用深度优先方法搜索,而分支限界一般用宽度优先或最佳优先方法来搜索。
-对扩展结点的扩展方式不同:
分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就 一次性产生其所有儿子结点。

实验报告分支限界法01背包

实验报告分支限界法01背包

实验报告分支限界法01背包实验报告:分支限界法解决01背包问题一、引言背包问题是数学和计算机科学中一个经典的问题。

背包问题通常分为01背包问题和完全背包问题两种情况。

本实验主要探讨的是分支限界法解决01背包问题,该算法常用于解决NP难问题。

分支限界法通过将问题分解为一系列子问题,并借助剪枝技术,逐步缩小问题的空间,从而找到最优解。

本实验将通过具体的案例来展示分支限界法的求解过程和原理,并对算法的时间复杂度和空间复杂度进行分析。

二、算法原理01背包问题的数学模型为:有n个物品,每个物品有一个重量wi和一个价值vi,在限定的背包容量为W的情况下,如何选择物品放入背包,使得背包中物品的总价值最大。

分支限界法的基本思想是:通过不断地分解问题为更小的子问题,并使用估算函数对子问题进行优先级排序,将优先级最高的子问题优先求解。

具体步骤如下:1.根节点:将背包容量W和物品序号0作为初始状态的根节点。

2.扩展节点:对于任意一个节点S,选择装入下一个物品或者不装入两种分支。

计算新节点的上界。

3.优先级队列:将扩展节点按照上界从大到小的顺序插入优先级队列。

4.剪枝条件:当扩展节点的上界小于当前已找到的最优解时,可以剪枝。

5.结束条件:当到叶节点或者队列为空时,结束。

若叶节点的上界高于当前最优解,更新最优解。

三、实验过程1.输入数据:给定一个物品序列,每个物品有重量和价值,以及一个背包的最大容量。

2.算法实现:根据算法原理,使用编程语言实现分支限界法的求解过程。

3.结果分析:比较算法求解得到的最优解和其他算法(如动态规划)得到的最优解之间的差异。

四、实验结果以一个具体的案例来说明分支限界法的求解过程。

假设有4个物品,其重量和价值分别为{2,3,4,5}和{3,4,5,6},背包的最大容量为8、通过分支限界法求解,得到最优解为9,对应的物品选择为{2,3,5}。

通过与动态规划算法的结果比较,可以发现分支限界法的最优解与动态规划算法得到的最优解是一致的。

分支界限方法01背包问题解题步骤

分支界限方法01背包问题解题步骤

分支界限方法是一种用于解决优化问题的算法。

在动态规划算法中,分支界限方法被广泛应用于解决01背包问题。

01背包问题是一个经典的动态规划问题,其解题步骤如下:1. 确定问题:首先需要明确01背包问题的具体描述,即给定一组物品和一个背包,每个物品有自己的价值和重量,要求在不超过背包容量的情况下,选取尽可能多的物品放入背包,使得背包中物品的总价值最大。

2. 列出状态转移方程:对于01背包问题,可以通过列出状态转移方程来描述问题的求解过程。

假设dp[i][j]表示在前i个物品中,背包容量为j时能够获得的最大价值,则状态转移方程可以表示为:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])3. 初始化边界条件:在动态规划中,需要对状态转移方程进行初始化,一般情况下,dp数组的第一行和第一列需要单独处理。

对于01背包问题,可以初始化dp数组的第一行和第一列为0。

4. 利用分支界限方法优化:针对01背包问题,可以使用分支界限方法来优化动态规划算法的效率。

分支界限方法采用广度优先搜索的思想,在每一步选择最有希望的分支,从而减少搜索空间,提高算法的效率。

5. 实际解题步骤:根据上述步骤,实际解决01背包问题的步骤可以概括为:确定问题,列出状态转移方程,初始化边界条件,利用分支界限方法优化,最终得到问题的最优解。

分支界限方法在解决01背包问题时起到了重要的作用,通过合理的剪枝策略,可以有效地减少动态规划算法的时间复杂度,提高问题的求解效率。

分支界限方法也可以应用于其他优化问题的求解过程中,在算法设计和实现中具有重要的理论和实际意义。

在实际应用中,分支界限方法需要根据具体问题进行灵活选择和调整,结合动态规划和剪枝策略,以便更好地解决各类优化问题。

掌握分支界限方法对于解决复杂问题具有重要的意义,也是算法设计和优化的关键技术之一。

分支界限方法在解决01背包问题的过程中,具有重要的作用。

试验4用分支限界法实现0-1背包问题

试验4用分支限界法实现0-1背包问题

0-1背包问题用分支限界法实现实验四一.实验目的 1.熟悉分支限界法的基本原理。

2.通过本次实验加深对分支限界法的理解。

二.实验内容及要求,背包容量为内容:.给定n种物品和一个背包。

物品i的重量是w,其价值为v? c。

问应该如何选择装入背包的物品,使得装入背包中物品的总价值最大背包问题0-1要求:使用优先队列式分支限界法算法编程,求解三.程序列表#include<iostream>#include<stack>std; using namespace100#define N class HeapNode//定义HeapNode结点类{: public weightprice double upper, price, weight; //upper为结点的价值上界,是结点所对应的价值,为结点所相应的重量//]; 活节点在子集树中所处的层序号N int level, x[};i); intdouble MaxBound( Knap();double是价值上界, ch, //up int level);booldoubledoubledoublevoid AddLiveNode( up, cp, cw, cwcp是相应的价值,是该结点所相应的重量,ture or falsech是 . . . .//最大队High HeapNodestack<> High;把物品重量和价值定义为双精度浮点数]; double w[N], p[N//为当前价值,定义背包容量为c//cw double cw, cp, c; 为当前重量,cp//货物数量为 n; int main() int{endl; <<请输入背包容量:cout <<c;cin >> endl; << cout <<请输入物品的个数: n;cin >> endl; <<请按顺序分别输入物品的重量:<< couti;int (i = 1; i <= n; i++) for//cin >> w[i]; 输入物品的重量endl; <<请按顺序分别输入物品的价值: cout <<(i = 1; i <= n; i++) for//输入物品的价值>> cin p[i];;最优值为:<< cout 函数输出最大价值knap//<<<<cout Knap() endl; 调用0;return}k MaxBound(doubleint函数求最大上界//MaxBound ){cleft = c - cw; double//剩余容量价值上界//double b = cp;. . . .//以物品单位重量价值递减装填剩余容量k while (k <= n&&w[] <= cleft){]; k cleft -= w[]; k b += p[++;k}<= n) (k if装填剩余容量装满背包] / w[ b += p[kk ] * cleft; //b;return}将一个新的活结点int lev//) , , , , AddLiveNode(voiddouble up double cp double cw bool ch插入到子集数和最大堆High中{be; HeapNode; up be.upper =; cp be.price =; be.weight = cw; be.level = lev <= n) if (lev High.push(be);} 函数调用}//stack头文件的push bestx double Knap() //优先队列分支限界法,返回最大价值,返回最优解{i = 1; intcw = cp = 0;. . . .double//best为当前最优值 bestp = 0;// up = MaxBound(1);价值上界double搜索子集空间树//while (1) //非叶子结点{wt = cw + w[i];doubleif (wt <= c) //左儿子结点为可行结点{(cp + p[i]>bestp) if bestp = cp + p[i];, i + 1);true AddLiveNode(up, cp + p[i], cw + w[i],}up = MaxBound(i + 1);右子数可能含最优解if (up >= bestp) //, i + 1); AddLiveNode(up, cp, cw, false (High.empty()) if bestp;return取下一扩展结点 //HeapNode node = High.top();High.pop();cw = node.weight;cp = node.price;up = node.upper;i = node.level;}四.实验结果} . . . .. . . .。

分支限界法解决01背包问题

分支限界法解决01背包问题

分⽀限界法解决01背包问题1. 问题描述设有n个物体和⼀个背包,物体i的重量为wi价值为pi ,背包的载荷为M, 若将物体i(1<= i <=n)装⼊背包,则有价值为pi . ⽬标是找到⼀个⽅案, 使得能放⼊背包的物体总价值最⾼.设N=3, W=(16,15,15), P=(45,25,25), C=30(背包容量)2. 队列式分⽀限界法可以通过画分⽀限界法状态空间树的搜索图来理解具体思想和流程每⼀层按顺序对应⼀个物品放⼊背包(1)还是不放⼊背包(0)步骤:①⽤⼀个队列存储活结点表,初始为空② A为当前扩展结点,其⼉⼦结点B和C均为可⾏结点,将其按从左到右顺序加⼊活结点队列,并舍弃A。

③按FIFO原则,下⼀扩展结点为B,其⼉⼦结点D不可⾏,舍弃;E可⾏,加⼊。

舍弃B④ C为当前扩展结点,⼉⼦结点F、G均为可⾏结点,加⼊活结点表,舍弃C⑤扩展结点E的⼉⼦结点J不可⾏⽽舍弃;K为可⾏的叶结点,是问题的⼀个可⾏解,价值为45⑥当前活结点队列的队⾸为F, ⼉⼦结点L、M为可⾏叶结点,价值为50、25⑦ G为最后⼀个扩展结点,⼉⼦结点N、O均为可⾏叶结点,其价值为25和0⑧活结点队列为空,算法结束,其最优值为50注:活结点就是不可再进⾏扩展的节点,也就是两个⼉⼦还没有全部⽣成的节点3. 优先队列式分⽀限界法3.1 以活结点价值为优先级准则步骤:①⽤⼀个极⼤堆表⽰活结点表的优先队列,其优先级定义为活结点所获得的价值。

初始为空。

②由A开始搜索解空间树,其⼉⼦结点B、C为可⾏结点,加⼊堆中,舍弃A。

③B获得价值45,C为0. B为堆中价值最⼤元素,并成为下⼀扩展结点。

④ B的⼉⼦结点D是不可⾏结点,舍弃。

E是可⾏结点,加⼊到堆中。

舍弃B。

⑤ E的价值为45,是堆中最⼤元素,为当前扩展结点。

⑥ E的⼉⼦J是不可⾏叶结点,舍弃。

K是可⾏叶结点,为问题的⼀个可⾏解价值为45。

⑦继续扩展堆中唯⼀活结点C,直⾄存储活结点的堆为空,算法结束。

分支限界法之LC01背包

分支限界法之LC01背包
分支限界法之 LC01 背包 1.问题描述:已知有 N 个物品和一个可以容纳 M 重量的背包,每种物品 I 的重量为 WEIGHT, 一个只能全放入或者不放入,求解如何放入物品,可以使背包里的物品的总效益最大。
2.设计思想与分析:对物品的选取与否构成一棵解树,左子树表示不装入,右表示装入,通 过检索问题的解树得出最优解,并用结点上界杀死不符合要求的结点。
#include <iostream.h> struct good {
int weight; int benefit; int flag;//是否可以装入标记 };
int number=0;//物品数量 int upbound=0; int curp=0, curw=0;//当前效益值与重量 int maxweight=0; good *bag=NULL;
void Init_good() {
bag=new good [number];
for(int i=0; i<number; i++) { cout<<"请输入第件"<<i+1<<"物品的重量:"; cin>>bag[i].weight; cout<<"请输入第件"<<i+1<<"物品的效益:"; cin>>bag[i].benefit; bag[i].flag=0;//初始标志为不装入背包 cout<<endl; }
}
int getbound(int num, int *bound_u)//返回本结点的 c 限界和 u 限界 {
for(int w=curw, p=curp; num<number && (w+bag[num].weight)<=maxweight; num++) { w=w+bag[num].weight; p=w+bag[num].benefit; }

01背包分支限定法

01背包分支限定法

0—1背包问题一、实验目的学习掌握分支限定法思想。

二、实验内容用分支限定法求解0—1背包问题,并输出问题的最优解。

0—1背包问题描述如下:给定n种物品和一背包。

物品i的重量是Wi,其价值为Vi,背包的容量是c,问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。

三、实验条件Jdk1.5以上四、需求分析对于给定n种物品和一背包。

在容量最大值固定的情况下,要求装入的物品价值最大化。

五、基本思想:对物品的选取与否构成一棵解树,左子树表示不装入,右表示装入,通过检索问题的解树得出最优解,并用结点上界杀死不符合要求的结点。

六、详细设计/** Bound_Branch.java** Created on 2007年6月2日, 下午6:07** To change this template, choose Tools | Template Manager* and open the template in the editor.*/package sunfa;public class Bound_Branch {static double c;static int n;static double[]w;static double[]p;static double cw;static double cp;static int []bestX;static MaxHeap heap;//上界函数bound计算节点所相应价值的上界private static double bound(int i){double cleft=c-cw;double 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;}//addLiveNode将一个新的活节点插入到子集树和优先队列中private static void addLiveNode(double up,double pp,double ww,int lev,BBnode par,boolean ch){//将一个新的活节点插入到子集树和最大堆中BBnode b=new BBnode(par,ch);HeapNode node =new HeapNode(b,up,pp,ww,lev);heap.put(node);}private static double bbKnapsack(){// TODO 自动生成方法存根//优先队列式分支限界法,返回最大价值,bestx返回最优解//初始化BBnode enode=null;int i=1;double bestp=0;//当前最优值double up=bound(1);//当前上界while(i!=n+1){//非叶子节点//检查当前扩展节点的右儿子子节点double wt=cw+w[i];if(wt<=c){if(cp+p[i]>bestp)bestp=cp+p[i];addLiveNode(up,cp+p[i],cw+w[i],i+1,enode,true);}up=bound(i+1);if(up>=bestp)addLiveNode(up,cp,cw,i+1,enode,false);HeapNode node =(HeapNode)heap.removeMax();enode=node.liveNode;cw=node.weight;cp=node.profit;up=node.upperProfit;i=node.level;}for(int j=n;j>0;j--){bestX[j]=(enode.leftChild)?1:0;enode=enode.parent;}return cp;}public static double knapsack(double []pp,double []ww,double cc,int []xx){ //返回最大值,bestx返回最优解c=cc;n=pp.length-1;//定义以单位重量价值排序的物品数组Element[]q=new Element[n];double ws=0.0;double ps=0.0;for(int i=1;i<=n;i++){q[i-1]=new Element(i,pp[i]/ww[i]);ps+=pp[i];ws+=ww[i];}if(ws<=c){for(int i=1;i<=n;i++)xx[i]=1;return ps;}//以单位重量排序MergeSort.mergeSort(q);//初始化数据成员p=new double[n+1];w=new double[n+1];for(int i=1;i<=n;i++){p[i]=pp[q[n-i].id];w[i]=ww[q[n-i].id];}cw=0.0;cp=0.0;bestX = new int[n+1];heap = new MaxHeap(n);double maxp = bbKnapsack();for(int i=1;i<=n;i++)xx[q[n-i].id]=bestX[i];return maxp;}public static void main(String [] args){double w[]={2,2,6,5,4};double v[]={6,3,4,5,6};double c=10;int []x = new int[5];double m = knapsack(v,w,c,x);for(int i=0;i<5;i++)System.out.print(x[i]);}}//子空间中节点类型class BBnode{BBnode parent;//父节点boolean leftChild;//左儿子节点标志BBnode(BBnode par,boolean ch){parent=par;leftChild=ch;}}class HeapNode implements Comparable{BBnode liveNode; // 活节点double upperProfit; //节点的价值上界double profit; //节点所相应的价值double weight; //节点所相应的重量int level; // 活节点在子集树中所处的层次号//构造方法public HeapNode(BBnode node, double up, double pp , double ww,int lev){ liveNode = node;upperProfit = up;profit = pp;weight = ww;level = lev;}public int compareTo(Object o) {double xup = ((HeapNode)o).upperProfit;if(upperProfit < xup)return -1;if(upperProfit == xup)return 0;elsereturn 1;}}class Element implements Comparable{int id;double d;public Element(int idd,double dd){id=idd;d=dd;}public int compareTo(Object x){double xd=((Element)x).d;if(d<xd)return -1;if(d==xd)return 0;return 1;}public boolean equals(Object x){return d==((Element)x).d;}}class MaxHeap{static HeapNode [] nodes;static int nextPlace;static int maxNumber;public MaxHeap(int n){maxNumber = (int)Math.pow((double)2,(double)n);nextPlace = 1;//下一个存放位置nodes = new HeapNode[maxNumber];}public static void put(HeapNode node){nodes[nextPlace] = node;nextPlace++;heapSort(nodes);}public static HeapNode removeMax(){HeapNode tempNode = nodes[1];nextPlace--;nodes[1] = nodes[nextPlace];heapSort(nodes);return tempNode;}private static void heapAdjust(HeapNode [] nodes,int s,int m){ HeapNode rc = nodes[s];for(int j=2*s;j<=m;j*=2){if(j<m&&nodes[j].upperProfit<nodes[j+1].upperProfit)++j;if(!(rc.upperProfit<nodes[j].upperProfit))break;nodes[s] = nodes[j];s = j;}nodes[s] = rc;}private static void heapSort(HeapNode [] nodes){for(int i=(nextPlace-1)/2;i>0;--i){heapAdjust(nodes,i,nextPlace-1);}}}主程序运行结果:。

最新实验 4 用分支限界法实现0-1背包问题

最新实验 4 用分支限界法实现0-1背包问题

实验四用分支限界法实现0-1背包问题一.实验目的1.熟悉分支限界法的基本原理。

2.通过本次实验加深对分支限界法的理解。

二.实验内容及要求内容:.给定n种物品和一个背包。

物品i的重量是w,其价值为v,背包容量为c。

问应该如何选择装入背包的物品,使得装入背包中物品的总价值最大?要求:使用优先队列式分支限界法算法编程,求解0-1背包问题三.程序列表#include<iostream>#include<stack>using namespace std;#define N 100class HeapNode//定义HeapNode结点类{public:double upper, price, weight; //upper为结点的价值上界,price是结点所对应的价值,weight 为结点所相应的重量int level, x[N]; //活节点在子集树中所处的层序号};double MaxBound(int i);double Knap();void AddLiveNode(double up, double cp, double cw, bool ch, int level);//up是价值上界,cp是相应的价值,cw是该结点所相应的重量,ch是ture or falsestack<HeapNode> High; //最大队Highdouble w[N], p[N]; //把物品重量和价值定义为双精度浮点数double cw, cp, c; //cw为当前重量,cp为当前价值,定义背包容量为cint n; //货物数量为int main(){cout <<"请输入背包容量:"<< endl;cin >> c;cout <<"请输入物品的个数:"<< endl;cin >> n;cout <<"请按顺序分别输入物品的重量:"<< endl;int i;for (i = 1; i <= n; i++)cin >> w[i]; //输入物品的重量cout <<"请按顺序分别输入物品的价值:"<< endl;for (i = 1; i <= n; i++)cin >> p[i]; //输入物品的价值cout <<"最优值为:";cout << Knap() << endl; //调用knap函数输出最大价值return 0;}double MaxBound(int k) //MaxBound函数求最大上界{double cleft = c - cw; //剩余容量double b = cp; //价值上界while (k <= n&&w[k] <= cleft) //以物品单位重量价值递减装填剩余容量{cleft -= w[k];b += p[k];k++;}if (k <= n)b += p[k] / w[k] * cleft; //装填剩余容量装满背包return b;}void AddLiveNode(double up, double cp, double cw, bool ch, int lev) //将一个新的活结点插入到子集数和最大堆High中{HeapNode be;be.upper = up;be.price = cp;be.weight = cw;be.level = lev;if (lev <= n)High.push(be);}//调用stack头文件的push函数 }double Knap() //优先队列分支限界法,返回最大价值,bestx返回最优解{int i = 1;cw = cp = 0;double bestp = 0; //best为当前最优值double up = MaxBound(1);//价值上界//搜索子集空间树while (1) //非叶子结点{double wt = cw + w[i];if (wt <= c) //左儿子结点为可行结点{if (cp + p[i]>bestp)bestp = cp + p[i];AddLiveNode(up, cp + p[i], cw + w[i], true, i + 1);}up = MaxBound(i + 1);if (up >= bestp) //右子数可能含最优解AddLiveNode(up, cp, cw, false, i + 1);if (High.empty())return bestp;HeapNode node = High.top(); //取下一扩展结点High.pop();cw = node.weight;cp = node.price;up = node.upper;i = node.level;}}四.实验结果酒店服务员年度工作汇报20xx年是自我挑战的一年,我将努力改正过去一年工作中的不足,把新一年的工作做好,过去的一年在领导的关心和同事的热情帮助,通过自身的不懈努力,在工作上取得了一定的成果,现将工作总结如下。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《算法设计与分析》实验报告六学号:1004091130 姓名:金玉琦日期:2011-11-17得分:一、实验内容:运用分支限界法解决0-1背包问题。

二、所用算法的基本思想及复杂度分析:分支限界法分支限界法按广度优先策略遍历问题的解空间树, 在遍历过程中, 对已经处理的每一个结点根据限界函数估算目标函数的可能取值, 从中选取使目标函数取得极值的结点优先进行广度优先搜索, 从而不断调整搜索方向, 尽快找到问题的解。

因为限界函数常常是基于问题的目标函数而确定的, 所以, 分支限界法适用于求解最优化问题。

0-1背包问题1)基本思想给定n 种物品和一个容量为C 的背包, 物品i 的重量是W i, 其价值为V i, 0/ 1 背包问题是如何选择装入背包的物品(物品不可分割) , 使得装入背包中物品的总价值最大,一般情况下, 解空间树中第i 层的每个结点, 都代表了对物品1~i 做出的某种特定选择, 这个特定选择由从根结点到该结点的路径唯一确定: 左分支表示装入物品, 右分支表示不装入物品。

对于第i 层的某个结点, 假设背包中已装入物品的重量是w, 获得的价值是v, 计算该结点的目标函数上界的一个简单方法是把已经装入背包中的物品取得的价值v, 加上背包剩余容量W - w 与剩下物品的最大单位重量价值vi + 1/ wi + 1的积,于是,得到限界函数:u b = v + ( W - w) × ( vi + 1/ wi + 1 )根据限界函数确定目标函数的界[ down , up],然后, 按照广度优先策略遍历问题的空间树。

2)复杂度分析时间复杂度是O(2n);三、源程序及注释:#include<iostream>#include<cstdio>#include<conio.h>#include<iomanip>using namespace std;int *x;struct node{//结点表结点数据结构node *parent,//父结点指针*next; //后继结点指针int level,//结点的层bag,//节点的解cw,//当前背包装载量cp;//当前背包价值float ub; //结点的上界值};class Knap{private:struct node *front, //队列队首*bestp,*first; //解结点、根结点int *p,*w,n,c,*M;//背包价值、重量、物品数、背包容量、记录大小顺序关系long lbestp;//背包容量最优解public:void Sort();Knap(int *pp,int *ww,int cc,int nn);~Knap();float Bound(int i,int cw,int cp);//计算上界限node *nnoder(node *pa,int ba,float uub);//生成一个结点 ba=1生成左节点 ba=0生成右节点void addnode(node *nod);//将结点添加到队列中void deletenode(node *nod);//将结点队列中删除struct node *nextnode(); //取下一个void display(); //输出结果void solvebag(); //背包问题求解};Knap::Knap(int *pp,int *ww,int cc,int nn){int i;n=nn;c=cc;p=new int[n];w=new int[n];M=new int[n];for(i=0;i<n;i++){p[i]=pp[i];w[i]=ww[i];M[i]=i;}front=new node[1];front->next=NULL;lbestp=0;bestp=new node[1];bestp=NULL;Sort();}Knap::~Knap(){delete []first;delete []front;delete []bestp;delete []p;delete []w;}float Knap::Bound(int i,int cw,int cp){// 计算上界int cleft=c-cw;float b=(float)cp;while (i<n&&w[i]<=cleft){cleft-=w[i];b+=p[i];i++;}if (i<n) b+=1.0*p[i]/w[i]*cleft;return b;}node * Knap::nnoder(struct node *pa,int ba,float uub) {//生成一个新结点node * nodell=new(node);nodell->parent=pa;nodell->next=NULL;nodell->level=(pa->level)+1;nodell->bag=ba;nodell->ub=uub;if(ba==1){nodell->cw=pa->cw+w[pa->level];nodell->cp=pa->cp+p[pa->level] ;}else{nodell->cw=pa->cw;nodell->cp=pa->cp;}return(nodell);}void Knap::addnode(node *no){//将结点加入优先队列node *p=front->next,*next1=front;float ub=no->ub;while(p!=NULL){if(p->ub<ub){no->next=p;next1->next=no;break;}next1=p;p=p->next;}if(p==NULL){next1->next=no;}}node *Knap::nextnode(){//取上限最大结点node *p=front->next;front->next=p->next;return(p);}void Knap::Sort(){int i,j,k,kkl;float minl;for(i=1;i<n;i++){minl=1.0*p[i]/w[i];k=0;for(j=1;j<=n-i;j++){if(minl<1.0*p[j]/w[j]){minl=1.0*p[j]/w[j];swap(p[k],p[j]);swap(w[k],w[j]);swap(M[k],M[j]);k=j;}}}}void Knap::display(){int i;cout<<"最大价值是:"<<lbestp<<endl;for(i=n;i>=1;i--){x[M[i-1]]=bestp->bag;bestp=bestp->parent;}cout<<"变量值为:"<<endl;for(i=1;i<=n;i++)cout<<"x("<<setw(2)<<i<<")="<<x[i-1]<<endl;}void Knap::solvebag(){//背包问题求解int i;float ubb;node *aa;first=new node[1]; //根结点first->parent=NULL;first->next=NULL;first->level=0;first->cw=0;first->cp=0;first->bag=0;ubb=Bound(0,0,0);first->ub=ubb;front->next=first;while(front->next!=NULL){aa=nextnode();i=aa->level;if(i==n-1){if(aa->cw+w[i]<=c&&(long)(aa->cp+p[i])>lbestp){lbestp=aa->cp+p[i];bestp=nnoder(aa,1,(float)lbestp);}if((long)(aa->cp)>lbestp){lbestp=aa->cp;bestp=nnoder(aa,0,(float)lbestp);}}if(i<n-1){if(aa->cw+w[i]<=c&&Bound(i+1,aa->cw+w[i],aa->cp+p[i])>(float)lbestp){ubb=Bound(i,aa->cw+w[i],aa->cp+p[i]);addnode(nnoder(aa,1,ubb));}ubb=ubb=Bound(i,aa->cw,aa->cp);if(ubb>lbestp)addnode(nnoder(aa,0,ubb));}}display();}void main(){int c,n;int i=0;int *p;int *w;cout<<"请输入背包容量:"<<endl;cin>>c;cout<<"请输入物品数:"<<endl;cin>>n;x=new int[n];p=new int[n];w=new int[n];cout<<"请输入"<<n<<"个物品的重量:"<<endl;for(i=0;i<n;i++)cin>>w[i];cout<<"请输入"<<n<<"个物品价值:"<<endl;for(i=0;i<n;i++)cin>>p[i];x=new int[n];Knap knbag(p,w,c,n);knbag.solvebag();getch();return;}四、运行输出结果:五、调试和运行程序过程中产生的问题、采取的措施及获得的相关经验教训:解决该问题首先要确定一个合适的限界函数数, 并根据限界函数确定目标函数的界[down,up],然后按照广度优先策略遍历问题的解空间树,在分支结点上,依次搜索该结点的所有孩子结点,分别估算这些孩子结点的目标函数的可能取值,如果某孩子结点的目标函数可能取得的值超出目标函数的界, 则将其丢弃, 因为从这个结点生成的解不会比目前已经得到的解更好; 否则, 将其加入待处理结点表中。

相关文档
最新文档