(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;
		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




版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/whzhaochao/article/details/12716301

智能推荐

django1.7 HTML模板中{%url%}的使用_weixin_34037515的博客-程序员秘密

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

卷积神经网络(CNN)_weixin_30660027的博客-程序员秘密

一、引言  神经网络不是具体的算法,而是一种模型构造的思路或者方式,BP神经网络是通过线性分类器后面直接跟随激励神经元,然后前后收尾相连接形成网络的方式。每一个神经元节点的输入都来自于上一层的每个神经元的输出,这种方式叫做“全连接”。当然BP神经网络也可以不是全连接的,后面会讲到。  全连接的好处在于从他的连接方式上看是每个输入维度的信息都会传播到其后的任意一个结点中去,会最大程度地让整个...

前馈神经网络_我没吐但是我秃了的博客-程序员秘密

神经网络的引出逻辑回归得限制这里的逻辑回归所能做的分界线就是一条直线,没有办法将红蓝色用一条直线分开。没办法将红蓝色用一条直线分开特征转换可以将很多的逻辑回归接到一起,就可以进行特征转换。比如上图就用两个逻辑回归 对z1,z2z_1,z_2z1​,z2​ 来进行特征转换,然后对于 x1′,x2′x_1^{'},x_2^{'}x1′​,x2′​ ​ ,再用一个逻辑回归zz来进行分...

SSM框架之一个简单的增删改查Demo_Wwwwei_csdn的博客-程序员秘密

学习SSM框架那些事儿作者 Wwwwei转载请注明原创出处,谢谢!前言  之前我们已经搭建好了SSM框架的基本工程结构,本文将会举一个简单的Demo用于说明SSM框架下增删改查的用法。数据库准备工作创建一个数据库  为了和之间搭建的工程保持一致,我在这里将数据库命名为ssm_db,编码方式采用UTF-8。  关于SSM框架数据库部分内容可以参考 SSM框架之JDBC配置创建表结构

版本号80之后的Chrome 关闭第三扩展提示的方法_FuckTheWindows的博客-程序员秘密

随着 Chrome 的扩展(extensions)政策越来越严苛,更新到最新版 Chrome 80 后安装非官方商店扩展的方法不仅更麻烦了1,使用这些非官方扩展的用户还会在每次启动 Chrome 浏览器后看到如下警告信息:对于大部分工作内容都要依靠浏览器的人而言,这样一则警告不仅会反复造成视觉干扰,启动后强行抢占窗口焦点的行为也让其它浏览器快捷键一时间失去了作用,必须先手动关掉这个警告才能...

Codeforces Round #262 (Div. 2)-A,B,C,D_codeforces262c_青竹梦的博客-程序员秘密

A. Vasya and Socks水题就不用多说了,直接暴力枚举就完事了。#include #include#include#include#include#include#includeusing namespace std;#define LL __int64int main(){ int n,k; while(~scanf("%d%d",&n,&

随便推点

YOLO2原理理解_yolo用2*2卷积核_hai_xiao_tian的博客-程序员秘密

YOLO改进策略:1.Bath Nomalization        Bath Nomalization可以提升模型收敛速度,而且可以起到一定正则化效果,降低模型的过拟合。        YOlLOv2中,在每个卷积后面都添加了Bathch Normalization层,并且不再使用droput,mAP提升了2.4%2.High Resolution Classifier        目前大部...

递推法c语言程序,最小二乘法,递推最小二乘法C语言源程序_夏天的柯比的博客-程序员秘密

最小二乘法,递推最小二乘法C语言源程序//init input#define row_y 29#define col_y 4double uk[31]={ 0,1.147,0.201,-0.787,-1.589,-1.052,0.866,1.152,1.573,0.626,0.433,-0.958,0.810,-0.044,0.947,-1.474,-0.719,-0.086,-1.099,1.4...

健康常识_我行我速的博客-程序员秘密

健康常识 1、常吃宵夜,会得胃癌,因为胃得不到休息。2、一个星期只能吃四颗蛋,吃太多对身体不好。3、鸡屁股含有致癌物,不要吃较好。4、饭后吃水果是错误的观念,应是饭前吃水果。5、女生月经来时,不要喝绿茶,反正茶类的不要喝就对了,多吃可以补血的东西。6、喝豆浆时,不要加鸡蛋及糖,也不要喝太多。7、空腹时不要吃蕃茄,最好饭后吃。8、早上醒来,先喝一杯水,预防结石。9、睡

用 Hadoop 进行分布式并行编程Ⅰ(转)_weixin_30648587的博客-程序员秘密

用 Hadoop 进行分布式并行编程Ⅰ(转) 2008-06-06 14:42Hadoop 简介 Hadoop 是一个开源的可运行于大规模集群上的分布式并行编程框架,由于分布式存储对于分布式编程来说是必不可少的,这个框架中还包含了一个分布式文件系统 HDFS( Hadoop Distributed File Sy...

[extjs]Ext.MessageBox.confirm应用_弱水垂钓的博客-程序员秘密

项目中经常会用到确认对话框,而Ext.MessageBox.confirm的返回值是MessageBox本身this那我们该如何应用confirm呢?下面看api说明confirm( String title, String msg, [Function fn], [Object scope] ) : Ext.MessageBoxDisplays a confirmation mes

thinkphp5错误:类型错误: Argument 1 passed to think\Hook::import() must be of the type array_MarsWill的博客-程序员秘密

点击进入视频教程使用thinkPHP5的时候出现如下错误类型错误: Argument 1 passed to think\Hook::import() must be of the type array, integer given, called in /data/php/college/thinkphp/library/think/App.php on line 509问题原因分析在我使用thi

推荐文章

热门文章

相关标签