• (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;
    		else
    			return 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);
    		}
    	}
    } ;
    
    
    #endif
    2.测试代码

    #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
    
    



  • 相关阅读:
    Django之权限用法
    Django之stark组件的使用和总结
    Django之stark组件2
    Wmic
    Powershell + HTA
    IFG以太网帧间隙
    python编译报错
    C# 格式化XML方法
    C#开发中常用的加密解密方法
    面试题
  • 原文地址:https://www.cnblogs.com/whzhaochao/p/5023505.html
Copyright © 2020-2023  润新知