1、实验指导书实验8分支限界法2算法设计与分析实验指导书(计算机科学与技术系)编写 兰州交通大学电子与信息工程学院2018年3月实验7 分支限界法-1一、实验目的(1)掌握分支限界法的各种不同的具体方法,包括队列式、改进的队列式以及优先队列式的区别。(2)通过实验掌握分支限界法思想和方法;(3)培养学生的动手能力。二、实验仪器设备(1)计算机;(2)C+编译调试环境。三、实验原理掌握将算法转换为可运行程序的步骤。四、实验内容及注意事项(1)装载问题。五、实验步骤5.1 装载问题1) 最基本的队列式分支限界法。只计算最优值,没有计算最优解。#include stdafx.h#include #inc
2、lude #include using namespace std;/子函数,将当前活节点加入队列templatevoid EnQueue(queue &Q, Type wt, Type &bestw, int i, int n) if (i = n) /可行叶结点 if (wtbestw) bestw = wt; else Q.push(wt); /非叶结点/装载问题先尽量将第一艘船装满/队列式分支限界法,返回最优载重量templateType MaxLoading(Type w, Type c, int n) /初始化数据 queue Q; /保存活节点的队列 Q.push(-1); /-
3、1的标志是标识分层 int i = 1; /i表示当前扩展节点所在的层数 Type Ew = 0; /Ew表示当前扩展节点的重量 Type bestw = 0; /bestw表示当前最优载重量 /搜索子集空间树 while (true) if (Ew + wi = c) /检查左儿子 EnQueue(Q, Ew + wi, bestw, i, n); /将左儿子添加到队列 /将右儿子添加到队列 即表示不将当前货物装载在第一艘船 EnQueue(Q, Ew, bestw, i, n); Ew = Q.front(); Q.pop(); /取下一个节点为扩展节点并将重量保存在Ew if (Ew =
4、 -1) /检查是否到了同层结束 if (Q.empty() return bestw; /遍历完毕,返回最优值 Q.push(-1); /添加分层标志 Ew = Q.front(); Q.pop(); /删除分层标志,进入下一层 i+; return bestw;int main(int argc, char* argv) int w5 = 0, 1, 2, 3 ; int c = 5; int n = 3; int bestp = MaxLoading(w, c, n); cout best p= bestp endl; return 0;2) 改进的队列式分支限界法加入了进入右子树的上界
5、函数。#include stdafx.h#include #include #include using namespace std;templateType MaxLoading(Type w, Type c, int n) /初始化数据 queue Q; /保存活节点的队列 Q.push(-1); /-1的标志是标识分层 int i = 1; /i表示当前扩展节点所在的层数 Type Ew = 0; /Ew表示当前扩展节点的重量 Type bestw = 0; /bestw表示当前最优载重量 Type r = 0; for (int j = 2; j = n; j+) r += wj; /
6、搜索子集空间树 while (true) Type wt = Ew + wi; if (wt bestw) bestw = wt; if (ibestw & in) Q.push(Ew); Ew = Q.front(); Q.pop(); /取下一个节点为扩展节点并将重量保存在Ew if (Ew = -1) /检查是否到了同层结束 if (Q.empty() return bestw; /遍历完毕,返回最优值 Q.push(-1); /添加分层标志 Ew = Q.front(); Q.pop(); /删除分层标志,进入下一层 i+; r -= wi; int main(int argc, ch
7、ar* argv) int w5 = 0, 1, 2, 3 ; int c = 5; int n = 3; int bestp = MaxLoading(w, c, n); cout best p= bestp endl; return 0;3)队列式分支限界法,包含最优解#include stdafx.h#includeusing namespace std;template class Queuepublic: Queue(int MaxQueueSize = 50); Queue() delete queue; bool IsEmpty()const return front = rea
8、r; bool IsFull() return (rear + 1) % MaxSize = front) ? 1 : 0); T Top() const; T Last() const; Queue& Add(const T& x); Queue& AddLeft(const T& x); Queue& Delete(T &x); void Output(ostream& out)const; int Length() return (rear - front); private: int front; int rear; int MaxSize; T *queue;templateQueu
9、e:Queue(int MaxQueueSize) MaxSize = MaxQueueSize + 1; queue = new TMaxSize; front = rear = 0;templateT Queue:Top()const if (IsEmpty() cout queue:no element,no! endl; return 0; else return queue(front + 1) % MaxSize;templateT Queue :Last()const if (IsEmpty() cout queue:no element endl; return 0; else
10、 return queuerear;templateQueue& Queue:Add(const T& x) if (IsFull()cout queue:no memory endl; else rear = (rear + 1) % MaxSize; queuerear = x; return *this;templateQueue& Queue:AddLeft(const T& x) if (IsFull()cout queue:no memory endl; else front = (front + MaxSize - 1) % MaxSize; queue(front + 1) %
11、 MaxSize = x; return *this;templateQueue& Queue :Delete(T & x) if (IsEmpty()cout queue:no element(delete) endl; else front = (front + 1) % MaxSize; x = queuefront; return *this;templatevoid Queue :Output(ostream& out)const for (int i = rear%MaxSize; i = (front + 1) % MaxSize; i-) out queuei;template
12、ostream& operator (ostream& out, const Queue& x) x.Output(out); return out;const int N = 3;templateclass QNodepublic: template friend void EnQueue(QueueQNode*&Q, Type wt, int i, int n, Type bestw, QNode*E, QNode *&bestE, int bestx, bool ch); template friend Type MaxLoading(Type w, Type c, int n, int
13、 bestx);public: QNode *parent; /指向父节点的指针 bool LChild; /左儿子标识 Type weight; /节点所相应的载重量 ;/将活节点加入到活节点队列Q中 templatevoid EnQueue(QueueQNode*&Q, Type wt, int i, int n, Type bestw, QNode*E, QNode *&bestE, int bestx, bool ch) if (i = n)/可行叶节点 if (wt = bestw) /当前最优装载重量 bestE = E; bestxn = ch; return; /非叶节点 QN
14、ode *b; b = new QNode ; b-weight = wt; b-parent = E; b-LChild = ch; Q.Add(b);templateType MaxLoading(Type w, Type c, int n, int bestx)/队列式分支限界法,返回最优装载重量,bestx返回最优解 QueueQNode* Q; /活节点队列 Q.Add(0); /同层节点尾部标识 int i = 1; /当前扩展节点所处的层 Type Ew = 0, /扩展节点所相应的载重量 bestw = 0, /当前最优装载重量 r = 0; /剩余集装箱重量 int j; f
15、or (j = 2; j = n; j+) r += wj; QNode *E = 0, /当前扩展节点 *bestE=0; /当前最优扩展节点 while (true) /检查左儿子节点 Type wt = Ew + wi; 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)
16、/同层节点尾部 if (Q.IsEmpty() break; Q.Add(0); /同层节点尾部标识 Q.Delete(E); /取下一扩展节点 i+; /进入下一层 r -= wi; /剩余集装箱重量 Ew = E-weight; /新扩展节点所对应的载重量 /构造当前最优解 for (j = n - 1; j 0; j-) bestxj = bestE-LChild; bestE = bestE-parent; return bestw;int main() float c = 5; float w = 0, 1, 2, 3 ;/下标从1开始 int xN + 1; float bestw
17、; cout 轮船载重为: c endl; cout 待装物品的重量分别为: endl; int i; for (i = 1; i = N; i+) cout wi ; cout endl; bestw = MaxLoading(w, c, N, x); cout 分支限界选择结果为: endl; for (i = 1; i = N; i+) cout xi ; cout endl; cout 最优装载重量为: bestw endl; system(pause); return 0;4) 优先队列式分支限界法,包含最优解。#include stdafx.h#include #include #
18、include #include #include /vs2013 greater 模板需要包含这个头文件using namespace std;const int N = 4;class bbnode;templateclass HeapNode/去掉友元,学些阶段直接改publicpublic: operator Type() const return uweight; template friend bool operator (const HeapNode &n1, const HeapNode &n2) return n1.uweightn2.uweight; /最大堆,用 publ
19、ic: bbnode *ptr; /指向活节点在子集树中相应节点的指针 Type uweight; /活节点优先级(上界) int level; /活节点在子集树中所处的层序号;class bbnode /去掉友元public: bbnode *parent; /指向父节点的指针 bool LChild; /左儿子节点标识 ;/函数需要提前声明templatevoid AddLiveNode(bbnode *E, Type wt, bool ch, int lev);templateType MaxLoading(Type w, Type c, int n, int bestx);int ma
20、in() float c = 70; float w = 0, 20, 10, 26, 15 ;/下标从1开始 int xN + 1; float bestw; cout 轮船载重为: c endl; cout 待装物品的重量分别为: endl; for (int i = 1; i = N; i+) cout wi ; cout endl; bestw = MaxLoading(w, c, N, x); cout 分支限界选择结果为: endl; for (int i = 1; i = 4; i+) cout xi ; cout endl; cout 最优装载重量为: bestw endl;
21、system(pause); return 0;priority_queueHeapNode, vectorHeapNode, greaterHeapNode H;/将活节点加入到表示活节点优先队列的最大堆H中 templatevoid AddLiveNode(bbnode *E, Type wt, bool ch, int lev) bbnode *b = new bbnode; b-parent = E; b-LChild = ch; HeapNode N; N.uweight = wt; N.level = lev; N.ptr = b; H.push(N); /H.Insert(N);
22、/优先队列式分支限界法,返回最优载重量,bestx返回最优解 templateType MaxLoading(Type w, Type c, int n, int bestx) /定义剩余容量数组 Type *r = new Typen + 1; rn = 0; for (int j = n - 1; j0; j-) /第j层剩余集装箱的重量之和,比如w = 0, 20, 10, 26, 15 /则r3=15 r2=41,r1=51, r4用不到 /以r3为例,表示在第3层,剩余集装箱的重量之和 rj = rj + 1 + wj + 1; /初始化 int i = 1;/当前扩展节点所处的层
23、bbnode *E = 0;/当前扩展节点 Type Ew = 0; /扩展节点所相应的载重量 /搜索子集空间树 while (i != n + 1)/非叶子节点 /检查当前扩展节点的儿子节点 if (Ew + wi = c) cout adding Level i L child to queue, upbound= Ew + wi + ri endl; AddLiveNode( E, Ew + wi + ri, true, i + 1); /右儿子节点 cout adding Level i R child to queue, upbound= Ew + ri endl; AddLiveN
24、ode( E, Ew + ri, false, i + 1); /取下一扩展节点 HeapNode N; N = H.top(); H.pop();/H.DeleteMax(N);/非空 i = N.level; E = N.ptr; Ew = N.uweight - ri - 1;/N.uweight是上界,Ew是已经装入的,要减去剩余集装箱重量之和 cout Level i node has been POPED, uweight= N.uweight Ew= Ew0; j-) bestxj = E-LChild; E = E-parent; deleter; return Ew;六、实验数据整理与结果分析对各个算法的运行情况进行分析,根据复杂度分析所用计算机可接收的最大问题规模或者可在可接受时间内完成的问题的规模。七、实验总结在解空间树中进入遍历时,必须使用约束函数和限界函数进行剪枝以避免不必要的搜索。八、实验报告完成实验报告8。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1