优先队列式分支限界法0-1背包
来源:互联网 发布:禁止软件联网 编辑:程序博客网 时间:2024/06/08 03:37
#include<iostream> #include <algorithm> #include "heap.h"using namespace std; class Knap { public: Knap(double *pp,double *ww,double cc,int nn)//构造函数 { p=pp; w=ww; c=cc; n=nn; cw=0; cp=0; E=0; bestx=new int[n+1]; H=init(100); } double knapsack();//找最优值的函数。 double Bound(int i);//边界函数 void AddLiveNode(double up,double cp,double cw,bool ch,int lev);int MaxKnapsack(); void output()//输出最佳路径 { for(int i=1;i<=n;i++) cout<<bestx[i]<<" "; cout<<endl; } private: double c; //背包容量 int n; //物品总数 double *w; //物品重量数组 double *p; //物品价值数组 double cw; //当前背包重量 double cp; //当前背包价值 bbnode *E; //指向扩展结点的指针 int *bestx; //最优解结构HeapQueue H; }; class Object { public: int ID; double d; }; int cmp(Object a,Object b)//定于排序类型。 { return a.d>b.d;//降序 } double Knap::Bound(int i) { Object *Q=new Object[n+1]; int j; for(j=1;j<=n;j++) { Q[j].ID=j; Q[j].d=1.0*p[j]/w[j]; } sort(Q+1,Q+n+1,cmp);/*对数组Q排序。按cmp()方式排序。这里要注意是从Q[1]开始而不是从Q开始*/ /*这里的Object 数组其实可以只创建一次就可以了,像现在这样每次调用Bound()都要创建并且对其进行排序,浪费资源,有待改进*//* for(j=1;j<=n;j++) cout<<Q[j].ID<<" "; cout<<endl; */ double cleft=c-cw; double b=cp; while(i<=n&&w[Q[i].ID]<=cleft) { cleft-=w[Q[i].ID]; b+=p[Q[i].ID]; i++; } if(i<=n) b+=1.0*p[Q[i].ID]*cleft/w[Q[i].ID];/*如果不能完整装入一个物品,则可以装入部分。*/ return b; } double Knap::knapsack() { /*分支判断,如果背包容量足够大,就不用再回溯搜索了。*/ int i; double W=0; double P=0; for(i=1;i<=n;i++) { W+=w[i]; P+=p[i]; } if(W<=c) //如果背包够大的话那么最优解就是全部了。bestx[]=1;{for(int j=1;j<=n;j++)bestx[j]=1;return P; }/*如果背包容量不够大,则有最有的方案,使用优先队列方法。*/ return MaxKnapsack(); } void Knap::AddLiveNode(double up,double cp,double cw,bool ch,int lev){bbnode *b=new bbnode; b->parent=E; b->LChild=ch; HeapNode N;N.uprofit=up;N.profit=cp;N.weight=cw; N.level=lev; N.ptr=b; InsertMax(N,H); }int Knap::MaxKnapsack(){double bestp=0;//当前最优值double up=Bound(1);//价值上界//cout<<up<<endl;//输出为22int i=1;while(i != n + 1){//double wt=cw+w[i];//cout<<wt<<endl;if(cw+w[i]<=c){if(cp+p[i]>bestp)/*前面是cw+w[i]<=c,这里是当前价值加上这一物品的价值大于最优值时更新最优值bestp*/bestp=cp+p[i];AddLiveNode(up,cp+p[i],cw+w[i],true,i+1);//激活这一结点}up=Bound(i+1);//检查当前扩展结点的右儿子结点if(up>=bestp)AddLiveNode(up,cp,cw,false,i+1);//取出下一个扩展结点 HeapNode N; N=DeleteMax(H); E=N.ptr; cw=N.weight; cp=N.profit; up=N.uprofit; i=N.level;}//构造当前左右解for(int j=n;j>0;j--){bestx[j]=E->LChild;E=E->parent;}return cp;}int main() { int n=4; double c=7;//背包容量 /*注意点,这里的数组p[]和w[]的第一个元素是-100,这是因为我在操作过程中都是从数组元素的1开始的,而我们知道数组中第一个元素是0号元素,所以我这里用-100填上*/ double p[]={-100,9,10,7,4};//物品价值 double w[]={-100,3,5,2,1};//物品重量 Knap k=Knap(p,w,c,n); cout<<k.knapsack()<<endl; k.output(); return 1; }
</pre><pre class="cpp" name="code">
struct bbnode { bbnode *parent; bool LChild; }; struct HeapNode { bbnode *ptr; //指向活结点在子集树中相应结点的指针 double weight; //结点所相应的重量 double uprofit, //结点的价值上限 profit; //结点所相应的价值 int level; //活结点在子集树中所处的层序号}; /****************************************************************************/ /****************************************************************************/ typedef HeapNode ElemType; #define MaxData 32767 typedef struct Heap { int capacity; int size; HeapNode *Elem; }Heap,*HeapQueue; HeapQueue init(int maxElem) { HeapQueue H=new Heap; H->capacity=maxElem; H->size=0; H->Elem=new HeapNode[maxElem+1]; H->Elem[0].uprofit=MaxData; return H; } void InsertMax(ElemType x,HeapQueue H) { int i; for(i=++H->size;H->Elem[i/2].uprofit<x.uprofit;i/=2) H->Elem[i]=H->Elem[i/2];//此时i还没有进行i/2操作 H->Elem[i]=x; } ElemType DeleteMax(HeapQueue H) { int i,child; ElemType MaxElem,LastElem; //存储最大元素和最后一个元素。 MaxElem=H->Elem[1]; //堆是从第1号元素开始的。 LastElem=H->Elem[ H->size-- ]; //这里自动让size减少了。 for(i = 1 ; i * 2 <= H->size ; i = child) { child=i * 2; /*在节点有左右子树的时候,可能存在一个大一个小的情况,这时候我们就要找出最小的; 如果Child = H->Size则表明他没有右子树,这时候就没有必要比较了。 */ if(child != H->size && H->Elem[child+1].uprofit>H->Elem[child].uprofit) child++;//找最大的子树 if(LastElem.uprofit < H->Elem[child].uprofit) H->Elem[i]=H->Elem[child]; } H->Elem[i]=LastElem; return MaxElem; }
0 0
- 优先队列式分支限界法0-1背包
- 用优先队列式分支限界法解决0-1背包问题
- 0-1背包问题---分支限界法
- 分支限界---->0/1背包
- 优先队列分支限界法之单源最短路径
- 01背包的四种解法详解:动态规划,贪心法,回溯法,优先队列式分支限界法(C语言编写)
- 分支限界法之LC 0/1背包
- 算法java实现--分支限界法--0-1背包问题
- 0-1背包问题之分支限界法
- 分支限界法的0-1背包问题Python实现
- 分支限界法解0-1背包问题
- 0/1背包问题的分支限界
- 最小重量机器设计问题——优先队列式分支限界法
- 优先队列式分支界限法之01背包问题
- 背包问题优先队列分枝限界算法
- 队列式和优先队列式分支限界算法的异同点
- 用分支限界解决0-1背包问题
- #分支限界法#最小机器重量设计问题(优先队列)
- 外键
- main()函数的实参
- 字典树 算法摘记
- shell编程基础二
- 怎样活得潇洒不累
- 优先队列式分支限界法0-1背包
- Ruby 学习易失点
- shell基础一
- Linux——IPC 基于文件的通信(普通文件 管道文件)
- NeHe OpenGL lesson 7
- 64位系统下使用PL/SQ(powerdesigner)连接oracel
- win上搭建cocos2dx开发环境
- 集团信息化之路—电子采购软件与现有库存及财务软件数据对接的探讨
- 邮票分你一半