01背包问题 分支界限法.docx
- 文档编号:28153185
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:10
- 大小:16.44KB
01背包问题 分支界限法.docx
《01背包问题 分支界限法.docx》由会员分享,可在线阅读,更多相关《01背包问题 分支界限法.docx(10页珍藏版)》请在冰豆网上搜索。
01背包问题分支界限法
实验五01背包问题
一、实验内容:
运用分支限界法解决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的积,于是,得到限界函数:
ub=v+(W-w)×(vi+1/wi+1)
根据限界函数确定目标函数的界[down,up],然后,按照广度优先策略遍历问题的空间树。
2)复杂度分析
时间复杂度是O(2n);
三、实验结果:
四、源程序及注释:
#include
#include
#include
#include
#include
usingnamespacestd;
int*x;
structnode
{
//结点表结点数据结构
node*parent,//父结点指针
*next;//后继结点指针
intlevel,//结点的层
bag,//节点的解
cw,//当前背包装载量
cp;//当前背包价值
floatub;//结点的上界值
};
classKnap
{
private:
structnode*front,//队列队首
*bestp,*first;//解结点、根结点
int*p,*w,n,c,*M;//背包价值、重量、物品数、背包容量、记录大小顺序关系
longlbestp;//背包容量最优解
public:
voidSort();
Knap(int*pp,int*ww,intcc,intnn);
~Knap();
floatBound(inti,intcw,intcp);//计算上界限
node*nnoder(node*pa,intba,floatuub);//生成一个结点ba=1生成左节点ba=0生成右节点
voidaddnode(node*nod);//将结点添加到队列中
voiddeletenode(node*nod);//将结点队列中删除
structnode*nextnode();//取下一个
voiddisplay();//输出结果
voidsolvebag();//背包问题求解
};
Knap:
:
Knap(int*pp,int*ww,intcc,intnn)
{
inti;
n=nn;
c=cc;
p=newint[n];
w=newint[n];
M=newint[n];
for(i=0;i { p[i]=pp[i]; w[i]=ww[i]; M[i]=i; } front=newnode[1]; front->next=NULL; lbestp=0; bestp=newnode[1]; bestp=NULL; Sort(); } Knap: : ~Knap() { delete[]first; delete[]front; delete[]bestp; delete[]p; delete[]w; } floatKnap: : Bound(inti,intcw,intcp) {//计算上界 intcleft=c-cw; floatb=(float)cp; while(i { cleft-=w[i]; b+=p[i]; i++; } if(i returnb; } node*Knap: : nnoder(structnode*pa,intba,floatuub) {//生成一个新结点 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); } voidKnap: : addnode(node*no) {//将结点加入优先队列 node*p=front->next,*next1=front; floatub=no->ub; while(p! =NULL) { if(p->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); } voidKnap: : Sort() { inti,j,k,kkl; floatminl; for(i=1;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; } } } } voidKnap: : display() { inti; cout<<"最大价值是: "< for(i=n;i>=1;i--) { x[M[i-1]]=bestp->bag; bestp=bestp->parent; } cout<<"变量值为: "< for(i=1;i<=n;i++) cout<<"x("< (2)< } voidKnap: : solvebag() {//背包问题求解 inti; floatubb; node*aa; first=newnode[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 { 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(); } voidmain() { }intc,n; inti=0; int*p; int*w; cout<<"请输入背包容量: "< cin>>c; cout<<"请输入物品数: "< cin>>n; x=newint[n]; p=newint[n]; w=newint[n]; cout<<"请输入"< "< for(i=0;i cin>>w[i]; cout<<"请输入"< "< for(i=0;i cin>>p[i]; x=newint[n]; Knapknbag(p,w,c,n); knbag.solvebag(); getch(); system("pause"); return;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 01背包问题 分支界限法 01 背包 问题 分支 界限