分支限界法求解背包问题

合集下载

分支限界法结局0~1背包问题

分支限界法结局0~1背包问题

Bound( i ) cleft = c – cw; 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; }

此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结 点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为 止。
与回溯法区别
求解目标不同: 一般而言,回溯法的求解目标是找出解空间树中满 足的约束条件的所有解,而分支限界法的求解目标 则是尽快的找出满足约束条件的一个解。

搜索方法不同 回溯法使用深度优先方法搜索,而分支限界一般用宽 度优先或最佳优先方法来搜索;

按照队列先进先出(FIFO)原则选取下一个节点为扩展节点;
数据结构:队列
(2)优先队列式分支限界法

按照优先队列中规定的优先级选取优先级最高的节点成为当前 扩展节点。 数据结构:堆 最大优先队列:使用最大堆,体现最大效益优先

最小优先队列:使用最小堆,体现最小费用优先
【0-1背包问题】
物品数量n=3,重量w=(20,15,15),价值v=(40,25,25) 背包容量c=30,试装入价值和最大的物品? 解空间:{(0,0,0),(0,0,1),…,(1,1,1)}
分支限界法解决0/1背包问题
分支限界法思想概述 与回溯法区别 求解步骤 常见的两种分支限界法 0-1背包问题
分支限界法的基本思想
分支限界法基本思想

分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜 索问题的解空间树。

背包问题的分支定界法

背包问题的分支定界法

背包问题的分支定界法
背包问题的分支定界法是一种求解背包问题的有效方法。

分支定界法的基本思想是将问题分解为若干个子问题,通过逐个解决子问题来逼近原问题的解。

在背包问题中,分支定界法通过将问题分解为一系列背包问题,从最简单的情况开始逐步扩展问题的规模,从而逐步逼近最优解。

分支限界法求解:
1.初始化:首先确定问题的约束条件和目标函数,并初始化问题的解空间树。

解空间树是问题解的搜索空间,其中每个节点表示一个可能的解。

2.搜索:从根节点开始,按照广度优先或最小耗费优先的方式搜索解空间树。

在搜索过程中,每个节点代表一个子问题,通过对子问题进行求解,可以逐步逼近原问题的解。

3.剪枝:在搜索过程中,根据问题的约束条件和目标函数,对一些不可能成为最优解的节点进行剪枝,从而减少搜索空间的大小。

剪枝可以提高搜索效率,但需要注意避免剪枝过度导致最优解丢失。

4.求解:当搜索到叶子节点时,表示找到了一个可行的解。

此时需要对叶子节点进行评估,确定其是否为最优解。

如果叶子节点的价值大于当前最优解的价值,则更新最优解;否则将叶子节点加入到已访问节点集合中。

5.回溯:如果搜索到叶子节点时发现当前最优解的价值不小于已访问节点集合中的最大价值,则说明当前最优解已经是最优解或者已经超出了搜索空间的上限。

此时需要进行回溯操作,即从当前节点向上回溯到上一层节点,并继续搜索。

6.结束:当搜索到根节点时,表示已经搜索完了解空间树。

此时需要判断是否找到了最优解,如果没有找到则需要进一步调整搜索策略或调整问题的约束条件和目标函数。

背包问题的多种解法

背包问题的多种解法

一个最优解:w i X i Wi2w1X1nmaX v i X i 。

如果不是的话,设(y2,y3, , y n) 是这X i {0,1}( 2 i n) i2问题描述0/1 背包问题 :现有n种物品,对1<=i<=n ,已知第i种物品的重量为正整数 W i,价值为正整数 V i, 背包能承受的最大载重量为正整数W,现要求找出这n种物品的一个子集,使得子集中物品的总重量不超过 W 且总价值尽量大。

(注意:这里对每种物品或者全取或者一点都不取,不允许只取一部分)算法分析根据问题描述,可以将其转化为如下的约束条件和目标函数:n w i x i Wi 1i i(1)x i { 0,1}( 1 i n)nmax v i x i (2)i1于是,问题就归结为寻找一个满足约束条件( 1 ),并使目标函数式( 2 )达到最大的解向量X (x1, x2 ,x3, ......... , x n) 。

首先说明一下 0-1 背包问题拥有最优解。

假设(X i,X2,X3,……,Xn)是所给的问题的一个最优解,则(X2,X3,……,Xn)是下面问题的n n n个问题的一个最优解,则v i y i v i X i ,且w1X1 w i y i W 。

因此,i 2 i 2 i 2n n n物品1W2=3V2=12物品2W3=4V3=40物品3W4=5V4=25物品4V1X1 V i y i V1X1 V i V i X i,这说明(X i,y2,y3, ............................................................... ,y n)是所给的 0-1 背包问i 2 i 2 i 1题比(X i,X2,X3, ........................... , X n)更优的解,从而与假设矛盾。

穷举法:用穷举法解决0-1背包问题,需要考虑给定 n个物品集合的所有子集,找出所有可能的子集(总重量不超过背包重量的子集) ,计算每个子集的总重量,然后在他们中找到价值最大的子集。

分支界限方法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背包问题的过程中,具有重要的作用。

(C++)分支限界法求解背包问题

(C++)分支限界法求解背包问题

(C++)分⽀限界法求解背包问题1.beibao.h⽂件代码如下:#ifndef BEIBAO_H#define BEIBAO_H#include <math.h>//⼦空间中节点类型class BBnode{public:BBnode* parent; //⽗节点bool leftChild; //左⼉⼦节点标志BBnode(BBnode* par,bool ch){parent=par;leftChild=ch;}BBnode(){}};class HeapNode {public:BBnode* liveNode; // 活结点double upperProfit; //结点的价值上界double profit; //结点所相应的价值double weight; //结点所相应的重量int level; // 活结点在⼦集树中所处的层次号//构造⽅法HeapNode(BBnode* node, double up, double pp , double ww,int lev){liveNode = node;upperProfit = up;profit = pp;weight = ww;level = lev;}HeapNode(){}int compareTo(HeapNode o) {double xup =o.upperProfit;if(upperProfit < xup)return -1;if(upperProfit == xup)return 0;elsereturn 1;}};class Element {public:int id;double d;Element(){}Element(int idd,double dd){id=idd;d=dd;}int compareTo(Element x){double xd=x.d;if(d<xd)return -1;if(d==xd)return 0;return 1;}bool equals(Element x){return d==x.d;}};class MaxHeap{public:HeapNode *nodes;int nextPlace;int maxNumber;MaxHeap(int n){maxNumber = pow((double)2,(double)n);nextPlace = 1;//下⼀个存放位置nodes = new HeapNode[maxNumber];}MaxHeap(){}void put(HeapNode node){nodes[nextPlace] = node;nextPlace++;heapSort(nodes);}HeapNode removeMax(){HeapNode tempNode = nodes[1];nextPlace--;nodes[1] = nodes[nextPlace];heapSort(nodes);return tempNode;}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;}void heapSort(HeapNode * nodes){for(int i=(nextPlace-1)/2;i>0;--i){heapAdjust(nodes,i,nextPlace-1);}}} ;#endif2.测试代码#include <iostream>using namespace std;//⼦空间中节点类型#include "beibao.h"double c=30;const int n=3;double *w;double *p;double cw;double cp;int *bestX;MaxHeap * heap;//上界函数bound计算结点所相应价值的上界double bound(int i){double cleft=c-cw;double b=cp;while(i<=n&&w[i]<=cleft){cleft=cleft-w[i];b=b+p[i];i++;}//装填剩余容量装满背包if(i<=n)b=b+p[i]/w[i]*cleft;return b;}//addLiveNode将⼀个新的活结点插⼊到⼦集树和优先队列中void addLiveNode(double up,double pp,double ww,int lev,BBnode* par,bool ch){ //将⼀个新的活结点插⼊到⼦集树和最⼤堆中BBnode *b=new BBnode(par,ch);HeapNode node =HeapNode(b,up,pp,ww,lev);heap->put(node);}double MaxKnapsack(){//优先队列式分⽀限界法,返回最⼤价值,bestx返回最优解BBnode * enode=new BBnode();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 =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;}double knapsack(double *pp,double *ww,double cc,int *xx){//返回最⼤值,bestX返回最优解c=cc;//n=sizeof(pp)/sizeof(double);//定义以单位重量价值排序的物品数组Element *q=new Element[n];double ws=0.0;double ps=0.0;for(int i=0;i<n;i++){q[i]=Element(i+1,pp[i+1]/ww[i+1]);ps=ps+pp[i+1];ws=ws+ww[i+1];}if(ws<=c){return ps;}p=new double[n+1];w=new double[n+1];for(int i=0;i<n;i++){p[i+1]=pp[q[i].id];w[i+1]=ww[q[i].id];}cw=0.0;cp=0.0;bestX = new int[n+1];heap = new MaxHeap(n);double bestp = MaxKnapsack();for(int j=0;j<n;j++)xx[q[j].id]=bestX[j+1];return bestp;}void main(){w=new double[4];w[1]=16;w[2]=15;w[3]=15;p=new double[4];p[1]=45;p[2]=25;p[3]=25;int *x = new int[4];double m = knapsack(p,w,c,x);cout<<"*****分⽀限界法*****"<<endl;cout<<"*****物品个数:n="<<n<<endl;cout<<"*****背包容量:c="<<c<<endl;cout<<"*****物品重量数组:w= {"<<w[3]<<" "<<w[1]<<" "<<w[2]<<"}"<<endl; cout<<"*****物品价值数组:v= {"<<p[3]<<" "<<p[1]<<" "<<p[2]<<"}"<<endl; cout<<"*****最优值:="<<m<<endl;cout<<"*****选中的物品是:";for(int i=1;i<=3;i++)cout<<x[i]<<" ";cout<<endl;}3.测试结果:*****分⽀限界法**********物品个数:n=3*****背包容量:c=30*****物品重量数组:w= {15 16 15} *****物品价值数组:v= {25 45 25} *****最优值:=50*****选中的物品是:0 1 1。

分支限界法解决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,直⾄存储活结点的堆为空,算法结束。

蛮力法、动态规划法、回溯法和分支限界法求解01背包问题【精选】

蛮力法、动态规划法、回溯法和分支限界法求解01背包问题【精选】

一、实验内容:分别用蛮力法、动态规划法、回溯法和分支限界法求解0/1背包问题。

注:0/1背包问题:给定种物品和一个容量为的背包,物品的重n C i 量是,其价值为,背包问题是如何使选择装入背包内的物品,使得装i w i v 入背包中的物品的总价值最大。

其中,每种物品只有全部装入背包或不装入背包两种选择。

二、所用算法的基本思想及复杂度分析:1.蛮力法求解0/1背包问题:1)基本思想:对于有n 种可选物品的0/1背包问题,其解空间由长度为n 的0-1向量组成,可用子集数表示。

在搜索解空间树时,深度优先遍历,搜索每一个结点,无论是否可能产生最优解,都遍历至叶子结点,记录每次得到的装入总价值,然后记录遍历过的最大价值。

2)代码:#include<iostream>#include<algorithm>using namespace std;#define N 100//最多可能物体数struct goods //物品结构体{int sign;//物品序号int w;//物品重量int p;//物品价值}a[N];bool m(goods a,goods b){return (a.p/a.w)>(b.p/b.w);}int max(int a,int b){return a<b?b:a;}int n,C,bestP=0,cp=0,cw=0;int X[N],cx[N];/*蛮力法求解0/1背包问题*/int Force(int i){if(i>n-1){if(bestP<cp&&cw+a[i].w<=C){for (int k=0;k<n;k++)X[k]=cx[k];//存储最优路径bestP=cp;}return bestP;}cw=cw+a[i].w;cp=cp+a[i].p;cx[i]=1;//装入背包Force(i+1);cw=cw-a[i].w;cp=cp-a[i].p;cx[i]=0;//不装入背包Force(i+1);return bestP;}int KnapSack1(int n,goods a[],int C,int x[]){Force(0);return bestP;}int main(){goods b[N];printf("物品种数n: ");scanf("%d",&n);//输入物品种数printf("背包容量C: ");scanf("%d",&C);//输入背包容量for (int i=0;i<n;i++)//输入物品i 的重量w 及其价值v {printf("物品%d 的重量w[%d]及其价值v[%d]:",i+1,i+1,i+1);scanf("%d%d",&a[i].w,&a[i].p);b[i]=a[i];}int sum1=KnapSack1(n,a,C,X);//调用蛮力法求0/1背包问题printf("蛮力法求解0/1背包问题:\nX=[ ");for(i=0;i<n;i++)cout<<X[i]<<" ";//输出所求X[n]矩阵printf("]装入总价值%d\n",sum1);bestP=0,cp=0,cw=0;//恢复初始化}3)复杂度分析:蛮力法求解0/1背包问题的时间复杂度为:。

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

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

分⽀限界法解决01背包问题 分⽀限界法和之前讲的回溯法有⼀点相似,两者都是在问题的解的空间上搜索问题的解。

但是两者还是有⼀些区别的,回溯法是求解在解的空间中的满⾜的所有解,分⽀限界法则是求解⼀个最⼤解或最⼩解。

这样,两者在解这⼀⽅⾯还是有⼀些不同的。

之前回溯法讲了N后问题,这个问题也是对于这有多个解,但是今天讲的01背包问题是只有⼀个解的。

下⾯就讲讲分⽀限界法的基本思想。

分⽀限界法常以⼴度优先或以最⼩消耗(最⼤效益)优先的⽅式搜索问题的解空间树。

问题的解空间树是表⽰问题解空间的⼀颗有序树,常见的有⼦集树和排列树。

分⽀限界法和回溯法的区别还有⼀点,它们对于当前扩展结点所采⽤的扩展⽅式也是不相同的。

分⽀限界法中,对于每⼀个活结点只有⼀次机会成为扩展结点。

活结点⼀旦成为了扩展结点,就⼀次性产⽣其所有的⼦结点,⼦结点中,不符合要求的和⾮最优解的⼦结点将会被舍弃,剩下的⼦结点将加⼊到活结点表中。

再重复上⾯的过程,直到没有活结点表中没有结点,⾄此完成解决问题的⽬的。

分⽀限界法⼤致的思想就是上⾯的叙述,现在就可以发现,对于结点的扩展将会成为分⽀限界法的主要核⼼。

所以,分⽀限界法常见的有两种扩展结点的⽅式,1.队列式(FIFO)分⽀限界法,2.优先队列式分⽀限界法。

两种⽅法的区别就是对于活结点表中的取出结点的⽅式不同,第⼀种⽅法是先进先出的⽅式,第⼆种是按优先级取出结点的⽅式。

两中⽅法的区别下⾯也会提到。

在背包问题中还会提到⼀个⼦树上界的概念,其实就是回溯法中的剪枝函数,只不过,分⽀限界法⾥的剪枝函数改进了⼀些,剪枝函数同样也是分⽀限界法⾥⽐较重要的东西。

下⾯就讲⼀讲01背包问题的实现。

01背包问题和前⾯讲的背包问题的区别不⼤,就是01背包问题的物品不可以只放⼊部分,01背包问题的物品只能放⼊和不放⼊两个选择,这也是名字中01的原因。

其他的和背包问题相差不⼤,这⾥也不再累述。

算法的主体是⽐较容易想的,⾸先,将数据进⾏处理,这也是上⾯讲到的第⼆种取结点的⽅式(优先队列式)。

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

分支限界法求解背包问题/*此程序实现,分支限界法求解背包问题,分支限界法是根据上界=当前背包的价值+背包剩余载重* (剩余物品最大价值/质量)*/分支r 10 I 分S: 104 1.200060' 6 2.i/eeoe#i nclude <stdio.h> #i nclude <stdlib.h>#include <time.h>#include <sys/time.h>#include <assert.h>#define MAXSIZE 20000//#define BAGWEIGHT 200 int a[MAXSIZE] = {0};int array[MAXSIZE] = {0};int weightarray[MAXSIZE] = {0}; /* 存放各物品重量*/int valuearray[MAXSIZE] = {0}; /* 存放各物品价值*/int lastweight[MAXSIZE]={0}; int lastvalue[MAXSIZE]={0}; int qq=0;/* 上面的数组,变量都是蛮力法所用到,下面的都是分支限界法所用到*/ int BAGWEIGHT; /* 背包的载重*/int n; /* 物品的数量*/int weightarrayb[MAXSIZE] = {0}; intvaluearrayb[MAXSIZE] = {0}; float costarrayb[MAXSIZE] = {0}; intfinalb[MAXSIZE] = {0};int finalweightb[MAXSIZE] = {0};/* 从文件读取数据*/void readb()int nn = 1,ii = 1;int i = 1;FILE *fp;fp = fopen("in.dat","rb");while(!feof(fp)){if(fscanf(fp,"%d%d",&weightarrayb[nn],&valuearrayb[nn]) != EOF)nn++;i++;elsebreak;fclose(fp);printf(" weight ");printf("value\n");for(ii = 1;ii < nn;ii++)printf("no%d: %-5d%-5d",ii,weightarrayb[ii],valuearrayb[ii]);printf("\n");/* 把读取的数据按照性价比从大到小排序*/ void rangeb()int i,j,k;int tempvalue,tempweight,tempcost;for(i = 1;i <= n;i++)printf(" weight ");costarrayb[i] = valuearrayb[i]/weightarrayb[i];for(j = 1;j <= n;j++)for(k = j;k <= n;k++)if(costarrayb[j] < costarrayb[k+1])tempcost = costarrayb[j];costarrayb[j] = costarrayb[k+1];costarrayb[k+1] = tempcost;tempweight = weightarrayb[j];weightarrayb[j] = weightarrayb[k+1];weightarrayb[k+1] = tempweight;tempvalue = valuearrayb[j];valuearrayb[j] = valuearrayb[k+1];valuearrayb[k+1] = tempvalue;printf("value ");printf("cost\n");for(i = 1;i <= n;i++)printf("no%d: %-5d%-5d %- f",i,weightarrayb[i],valuearrayb[i],costarrayb[i]); printf("\n");/* 分支限界法运算*/void branchb()int i,k,j,u = 1;int emptyweight = BAGWEIGHT;int tempweight = 0;int tempvalue = 0;float ub;float exub;int extempweightb[MAXSIZE] = {0};int extempvalueb[MAXSIZE] = {0};int exemptyweightb[MAXSIZE] = {0};int allweight = 0;int allvalue = 0;ub = tempvalue + emptyweight * costarrayb[1];exemptyweightb[0] = BAGWEIGHT;printf("include 0: weight=0 value=0 ub = %f\n",ub);printf("\n");i = 1;while(weightarrayb[i] != 0)tempweight = tempweight + weightarrayb[i];tempvalue = tempvalue + valuearrayb[i];emptyweight = BAGWEIGHT - tempweight;if(tempweight > BAGWEIGHT)printf("include %d: weight=%d can't\n",i,tempweight);tempweight = extempweightb[i-1];tempvalue = extempvalueb[i-1];emptyweight = exemptyweightb[i-1];ub = 0;elseub = tempvalue + emptyweight * costarrayb[i+1];printf("include %d: weight=%d value=%d ub=%f\n",i,tempweight,tempvalue,ub); extempvalueb[i] = tempvalue;extempweightb[i] = tempweight;exemptyweightb[i] = emptyweight;exub = extempvalueb[i-1] + exemptyweightb[i-1] * costarrayb[i+1]; printf("exclude %d: weight=%d value=%dub=%f\n",i,extempweightb[i-1],extempvalueb[i-1],exub);printf("\n");if(ub < exub || ub == 0)finalb[i] = 2;if(ub >= exub)finalb[i] = 1;i++;printf("the final answer is: ");for(i = 1;i <= n;i++)if(finalb[i] == 1)printf("%d ",i);finalweightb[u] = i;u++;else if(finalb[i] == 2)continue;printf("\n");for(i = 1;i <= u;i++)allweight = allweight + weightarrayb[finalweightb[i]]; allvalue = allvalue + valuearrayb[finalweightb[i]];printf("the final weight is :%d\n",allweight);printf("the final value is : %d\n",allvalue);/* 自动生成文件*/void become()int i;FILE *fp;fp = fopen("in.dat","w");//srand(unsigned(time(NULL)));for(i=0;i<n;i++)fprintf(fp,"%d %d\n",rand()%9+1,rand()%41+10);fclose(fp);/* 删除文件*/void del()remove("in.dat");int main()printf(" 请输入背包负重(大于0 的整数):"); scanf("%d",&BAGWEIGHT);printf(" 请输入物品数量(大于0 的整数):"); scanf("%d",&n);float time_usea=0;float time_useb=0;struct timeval starta;struct timeval enda;struct timeval startb;struct timeval endb;int k = 0,i,j,u,loop;loop=0;gettimeofday(&startb,NULL);become();readb();由于分支限界太效率,时常显示 0 毫秒,为了能读出时间,让其运行 100 次后总时间再除以 100*/rangeb();branchb();gettimeofday(&endb,NULL);time_useb=(__sec)*1000+(_usec- _usec)/1000;// 毫秒printf("\n");for(i=0;i<100;i++) /*printf("It took you %f 毫秒\n", time_useb/100);/* 最后把算到的时间读出到文件*/FILE *fp = NULL;fp = fopen("OUT.DAT", "a+");if(NULL == fp)printf("wrong");return 0;//fprintf(fp, " 蛮力: %d %d %f\n", BAGWEIGHT,n,time_usea); fprintf(fp, " 分支: %d %d %f\n", BAGWEIGHT,n,time_useb/100); fclose(fp);del(); /* 要运算多次,生成多次文件,所以每次算完删除文件*/printf(" 如果需要再算一次,请按1\n"); printf(" 如果需要退出,请按2\n"); scanf("%d",&loop);switch(loop)case 1:return main();case 2:return;default:return;return 0;}。

相关文档
最新文档