实验指导书实验8分支限界法2.docx

上传人:b****0 文档编号:12723317 上传时间:2023-04-21 格式:DOCX 页数:19 大小:20.32KB
下载 相关 举报
实验指导书实验8分支限界法2.docx_第1页
第1页 / 共19页
实验指导书实验8分支限界法2.docx_第2页
第2页 / 共19页
实验指导书实验8分支限界法2.docx_第3页
第3页 / 共19页
实验指导书实验8分支限界法2.docx_第4页
第4页 / 共19页
实验指导书实验8分支限界法2.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

实验指导书实验8分支限界法2.docx

《实验指导书实验8分支限界法2.docx》由会员分享,可在线阅读,更多相关《实验指导书实验8分支限界法2.docx(19页珍藏版)》请在冰豆网上搜索。

实验指导书实验8分支限界法2.docx

实验指导书实验8分支限界法2

算法设计与分析

实验指导书

(计算机科学与技术系)

 

编写

 

 

兰州交通大学电子与信息工程学院

2018年3月

 

实验7分支限界法-1

一、实验目的

(1)掌握分支限界法的各种不同的具体方法,包括队列式、改进的队列式以及优先队列式的区别。

(2)通过实验掌握分支限界法思想和方法;

(3)培养学生的动手能力。

二、实验仪器设备

(1)计算机;

(2)C++编译调试环境。

三、实验原理

掌握将算法转换为可运行程序的步骤。

四、实验内容及注意事项

(1)装载问题。

五、实验步骤

5.1装载问题

1)最基本的队列式分支限界法。

只计算最优值,没有计算最优解。

#include"stdafx.h"

#include

#include

#include

usingnamespacestd;

//子函数,将当前活节点加入队列

template

voidEnQueue(queue&Q,Typewt,Type&bestw,inti,intn)

{

if(i==n)//可行叶结点

{

if(wt>bestw)bestw=wt;

}

elseQ.push(wt);//非叶结点

}

//装载问题先尽量将第一艘船装满

//队列式分支限界法,返回最优载重量

template

TypeMaxLoading(Typew[],Typec,intn)

{

//初始化数据

queueQ;//保存活节点的队列

Q.push(-1);//-1的标志是标识分层

inti=1;//i表示当前扩展节点所在的层数

TypeEw=0;//Ew表示当前扩展节点的重量

Typebestw=0;//bestw表示当前最优载重量

//搜索子集空间树

while(true)

{

if(Ew+w[i]<=c)//检查左儿子

EnQueue(Q,Ew+w[i],bestw,i,n);//将左儿子添加到队列

//将右儿子添加到队列即表示不将当前货物装载在第一艘船

EnQueue(Q,Ew,bestw,i,n);

Ew=Q.front();Q.pop();//取下一个节点为扩展节点并将重量保存在Ew

if(Ew==-1)//检查是否到了同层结束

{

if(Q.empty())returnbestw;//遍历完毕,返回最优值

Q.push(-1);//添加分层标志

Ew=Q.front();Q.pop();//删除分层标志,进入下一层

i++;

}

}

returnbestw;

}

intmain(intargc,char*argv[])

{

intw[5]={0,1,2,3};

intc=5;

intn=3;

intbestp=MaxLoading(w,c,n);

cout<<"bestp="<

return0;

}

2)改进的队列式分支限界法

加入了进入右子树的上界函数。

#include"stdafx.h"

#include

#include

#include

usingnamespacestd;

template

TypeMaxLoading(Typew[],Typec,intn)

{

//初始化数据

queueQ;//保存活节点的队列

Q.push(-1);//-1的标志是标识分层

inti=1;//i表示当前扩展节点所在的层数

TypeEw=0;//Ew表示当前扩展节点的重量

Typebestw=0;//bestw表示当前最优载重量

Typer=0;

for(intj=2;j<=n;j++)

r+=w[j];

//搜索子集空间树

while(true)

{

Typewt=Ew+w[i];

if(wt<=c){//检查左儿子

if(wt>bestw)bestw=wt;

if(i

}

if(Ew+r>bestw&&i

Q.push(Ew);

Ew=Q.front();Q.pop();//取下一个节点为扩展节点并将重量保存在Ew

if(Ew==-1)//检查是否到了同层结束

{

if(Q.empty())returnbestw;//遍历完毕,返回最优值

Q.push(-1);//添加分层标志

Ew=Q.front();Q.pop();//删除分层标志,进入下一层

i++;

r-=w[i];

}

}

}

intmain(intargc,char*argv[])

{

intw[5]={0,1,2,3};

intc=5;

intn=3;

intbestp=MaxLoading(w,c,n);

cout<<"bestp="<

return0;

}

3)队列式分支限界法,包含最优解

#include"stdafx.h"

#include

usingnamespacestd;

template

classQueue

{

public:

Queue(intMaxQueueSize=50);

~Queue(){delete[]queue;}

boolIsEmpty()const{returnfront==rear;}

boolIsFull(){return(((rear+1)%MaxSize==front)?

1:

0);}

TTop()const;

TLast()const;

Queue&Add(constT&x);

Queue&AddLeft(constT&x);

Queue&Delete(T&x);

voidOutput(ostream&out)const;

intLength(){return(rear-front);}

private:

intfront;

intrear;

intMaxSize;

T*queue;

};

template

Queue:

:

Queue(intMaxQueueSize)

{

MaxSize=MaxQueueSize+1;

queue=newT[MaxSize];

front=rear=0;

}

template

TQueue:

:

Top()const

{

if(IsEmpty())

{

cout<<"queue:

noelement,no!

"<

return0;

}

elsereturnqueue[(front+1)%MaxSize];

}

template

TQueue:

:

Last()const

{

if(IsEmpty())

{

cout<<"queue:

noelement"<

return0;

}

elsereturnqueue[rear];

}

template

Queue&Queue:

:

Add(constT&x)

{

if(IsFull())cout<<"queue:

nomemory"<

else

{

rear=(rear+1)%MaxSize;

queue[rear]=x;

}

return*this;

}

template

Queue&Queue:

:

AddLeft(constT&x)

{

if(IsFull())cout<<"queue:

nomemory"<

else

{

front=(front+MaxSize-1)%MaxSize;

queue[(front+1)%MaxSize]=x;

}

return*this;

}

template

Queue&Queue:

:

Delete(T&x)

{

if(IsEmpty())cout<<"queue:

noelement(delete)"<

else

{

front=(front+1)%MaxSize;

x=queue[front];

}

return*this;

}

 

template

voidQueue:

:

Output(ostream&out)const

{

for(inti=rear%MaxSize;i>=(front+1)%MaxSize;i--)

out<

}

template

ostream&operator<<(ostream&out,constQueue&x)

{

x.Output(out);returnout;

}

constintN=3;

template

classQNode

{

public:

template

friendvoidEnQueue(Queue*>&Q,Typewt,inti,intn,Typebestw,QNode*E,QNode*&bestE,intbestx[],boolch);

template

friendTypeMaxLoading(Typew[],Typec,intn,intbestx[]);

public:

QNode*parent;//指向父节点的指针

boolLChild;//左儿子标识

Typeweight;//节点所相应的载重量

};

//将活节点加入到活节点队列Q中

template

voidEnQueue(Queue*>&Q,Typewt,inti,intn,Typebestw,QNode*E,QNode*&bestE,intbestx[],boolch)

{

if(i==n)//可行叶节点

{

if(wt==bestw)

{

//当前最优装载重量

bestE=E;

bestx[n]=ch;

}

return;

}

//非叶节点

QNode*b;

b=newQNode;

b->weight=wt;

b->parent=E;

b->LChild=ch;

Q.Add(b);

}

template

TypeMaxLoading(Typew[],Typec,intn,intbestx[])

{//队列式分支限界法,返回最优装载重量,bestx返回最优解

Queue*>Q;//活节点队列

Q.Add(0);//同层节点尾部标识

inti=1;//当前扩展节点所处的层

TypeEw=0,//扩展节点所相应的载重量

bestw=0,//当前最优装载重量

r=0;//剩余集装箱重量

intj;

for(j=2;j<=n;j++)

{

r+=w[j];

}

QNode*E=0,//当前扩展节点

*bestE=0;//当前最优扩展节点

while(true)

{

//检查左儿子节点

Typewt=Ew+w[i];

if(wt<=c)//可行节点

{

if(wt>bestw)

{

bestw=wt;

}

EnQueue(Q,wt,i,n,bestw,E,bestE,bestx,true);

}

//检查右儿子节点

if(Ew+r>bestw)

{

EnQueue(Q,Ew,i,n,bestw,E,bestE,bestx,false);

}

Q.Delete(E);//取下一扩展节点

if(!

E)//同层节点尾部

{

if(Q.IsEmpty())

{

break;

}

Q.Add(0);//同层节点尾部标识

Q.Delete(E);//取下一扩展节点

i++;//进入下一层

r-=w[i];//剩余集装箱重量

}

Ew=E->weight;//新扩展节点所对应的载重量

}

//构造当前最优解

for(j=n-1;j>0;j--)

{

bestx[j]=bestE->LChild;

bestE=bestE->parent;

}

returnbestw;

}

intmain()

{

floatc=5;

floatw[]={0,1,2,3};//下标从1开始

intx[N+1];

floatbestw;

cout<<"轮船载重为:

"<

cout<<"待装物品的重量分别为:

"<

inti;

for(i=1;i<=N;i++)

{

cout<

}

cout<

bestw=MaxLoading(w,c,N,x);

cout<<"分支限界选择结果为:

"<

for(i=1;i<=N;i++)

{

cout<

}

cout<

cout<<"最优装载重量为:

"<

system("pause");

return0;

}

4)优先队列式分支限界法,包含最优解。

#include"stdafx.h"

#include

#include

#include

#include

#include//vs2013greater模板需要包含这个头文件

usingnamespacestd;

constintN=4;

classbbnode;

template

classHeapNode

{

//去掉友元,学些阶段直接改public

public:

operatorType()const{returnuweight;}

template

friendbooloperator>(constHeapNode&n1,constHeapNode&n2)

{

returnn1.uweight

}

public:

bbnode*ptr;//指向活节点在子集树中相应节点的指针

Typeuweight;//活节点优先级(上界)

intlevel;//活节点在子集树中所处的层序号

};

classbbnode

{//去掉友元

public:

bbnode*parent;//指向父节点的指针

boolLChild;//左儿子节点标识

};

//函数需要提前声明

template

voidAddLiveNode(bbnode*E,Typewt,boolch,intlev);

template

TypeMaxLoading(Typew[],Typec,intn,intbestx[]);

intmain()

{

floatc=70;

floatw[]={0,20,10,26,15};//下标从1开始

intx[N+1];

floatbestw;

cout<<"轮船载重为:

"<

cout<<"待装物品的重量分别为:

"<

for(inti=1;i<=N;i++)

{

cout<

}

cout<

bestw=MaxLoading(w,c,N,x);

cout<<"分支限界选择结果为:

"<

for(inti=1;i<=4;i++)

{

cout<

}

cout<

cout<<"最优装载重量为:

"<

system("pause");

return0;

}

priority_queue,vector>,greater>>H;

//将活节点加入到表示活节点优先队列的最大堆H中

template

voidAddLiveNode(bbnode*E,Typewt,boolch,intlev)

{

bbnode*b=newbbnode;

b->parent=E;

b->LChild=ch;

HeapNodeN;

N.uweight=wt;

N.level=lev;

N.ptr=b;

H.push(N);//H.Insert(N);

}

//优先队列式分支限界法,返回最优载重量,bestx返回最优解

template

TypeMaxLoading(Typew[],Typec,intn,intbestx[])

{

//定义剩余容量数组

Type*r=newType[n+1];

r[n]=0;

for(intj=n-1;j>0;j--)

{//第j层剩余集装箱的重量之和,比如w[]={0,20,10,26,15}

//则r[3]=15r[2]=41,r[1]=51,r[4]用不到

//以r[3]为例,表示在第3层,剩余集装箱的重量之和

r[j]=r[j+1]+w[j+1];

}

//初始化

inti=1;//当前扩展节点所处的层

bbnode*E=0;//当前扩展节点

TypeEw=0;//扩展节点所相应的载重量

//搜索子集空间树

while(i!

=n+1)//非叶子节点

{

//检查当前扩展节点的儿子节点

if(Ew+w[i]<=c)

{

cout<<"addingLevel"<

AddLiveNode(E,Ew+w[i]+r[i],true,i+1);

}

//右儿子节点

cout<<"addingLevel"<

AddLiveNode(E,Ew+r[i],false,i+1);

//取下一扩展节点

HeapNodeN;

N=H.top();H.pop();//H.DeleteMax(N);//非空

i=N.level;

E=N.ptr;

Ew=N.uweight-r[i-1];//N.uweight是上界,Ew是已经装入的,要减去剩余集装箱重量之和

cout<<"Level"<

}

//构造当前最优解

for(intj=n;j>0;j--)

{

bestx[j]=E->LChild;

E=E->parent;

}

delete[]r;

returnEw;

}

六、实验数据整理与结果分析

对各个算法的运行情况进行分析,根据复杂度分析所用计算机可接收的最大问题规模或者可在可接受时间内完成的问题的规模。

七、实验总结

在解空间树中进入遍历时,必须使用约束函数和限界函数进行剪枝以避免不必要的搜索。

八、实验报告

完成实验报告8。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 其它模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1