版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、;.第六章 分支限界法1 学习要点1.1 学习要点理解分支限界法的剪枝搜索策略。掌握分支限界法的算法框架(1)队列式(FIFO)分支限界法(2)优先队列式分支限界法 通过应用范例学习分支限界法的设计策略。(1)单源最短路径问题(2)装载问题;(4)0-1背包问题;(8)批处理作业调度问题2 分支限界法的基本思想2.1 分支限界法描述采用广度优先产生状态空间树的结点,并使用剪枝函数的方法称为分支限界法。所谓“分支”是采用广度优先的策略,依次生成扩展结点的所有分支(即:儿子结点)。所谓“限界”是在结点扩展过程中,计算结点的上界(或下界),边搜索边减掉搜索树的某些分支,从而提高搜索效率。原理按照广度
2、优先的原则,一个活结点一旦成为扩展结点(E-结点)R后,算法将依次生成它的全部孩子结点,将那些导致不可行解或导致非最优解的儿子舍弃,其余儿子加入活结点表中。然后,从活结点表中取出一个结点作为当前扩展结点。重复上述结点扩展过程,直至找到问题的解或判定无解为止。2.2 分支限界法与回溯法求解目标:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。搜索方式的不同:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先的方式搜索解空间树。分支限界法常以广度优先或以最小耗费(最大效益)优先的方
3、式搜索问题的解空间树。在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。2.3 常见的两种分支限界法队列式(FIFO)分支限界法 按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。搜索策略:一开始,根结点是唯一的活结点,根结点入队。从活结点队中取出根结点后,作为当前扩展结点。对当前扩展结点,先从左到右地产生它的所有儿子,
4、用约束条件检查,把所有满足约束函数的儿子加入活结点队列中。再从活结点表中取出队首结点(队中最先进来的结点)为当前扩展结点,直到找到一个解或活结点队列为空为止。队列式分支限界法搜索解空间树的方式与解空间树的广度优先遍历算法极为相似,唯一的不同之处是队列式分支限界法不搜索以不可行结点为根的子树。优先队列式分支限界法 基本思想:为了加速搜索的进程,应采用有效的方式选择活结点进行扩展。按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。 搜索策略:对每一活结点计算一个优先级(某些信息的函数值),并根据这些优先级;从当前活结点表中优先选择一个优先级最高(最有利)的结点作为扩展结点,使搜索朝着
5、解空间树上有最优解的分支推进,以便尽快地找出一个最优解。再从活结点表中下一个优先级别最高的结点为当前扩展结点,直到找到一个解或活结点队列为空为止。3 0 -1背包问题3.1 算法思想首先,要对输入数据进行预处理,将各物品依其单位重量价值从大到小进行排列。在优先队列分支限界法中,节点的优先级由已装袋的物品价值加上剩下的最大单位重量价值的物品装满剩余容量的价值和。template<class Typew,class Typep>Typep Knap<Typew,Typep>:Bound(int i) /计算节点所相应价值的上界 Typew cleft = c-cw; /剩余
6、容量高 Typep b = cp; /价值上界 /以物品单位重量价值递减序装填剩余容量 while(i<=n && wi<=cleft) cleft -= wi; b += pi; i+; /装填剩余容量装满背包 if(i<=n) b += pi/wi*cleft; return b;算法首先检查当前扩展结点的左儿子结点的可行性。如果该左儿子结点是可行结点,则将它加入到子集树和活结点优先队列中,判断方法同回溯法。当前扩展结点的右儿子结点一定是可行结点,仅当右儿子结点满足上界约束时才将它加入子集树和活结点优先队列,判断方法同回溯法。当扩展到叶节点时为问题的最优值
7、。例如:0-1背包问题,当n=3时,w=16,15,15, p=45,25,25, c=30。优先队列式分支限界法处理法则:价值大者优先。取结点的当前价值排序(按照书本P162逻辑)。>A>B,C【>C,D(舍去),E】>E,C【>C,J(舍去),K】>K,C>F,G>G,L,M【>G,M(L,M已是叶节点)】>G>N,O>O>3.2 队列式(FIFO)算法示例解空间树如下图所示,1代表选择,0代表不选。分支限界法如下处理:可扩展结点:A 活结点队列:B,C选择路径 : AW:0P:0可扩
8、展结点:B; 活结点队列:C,D,E选择路径: A->BW:16P:45可扩展结点:C 活结点队列:D,E,F,G选择路径: A->CW:0 P:0如果扩展D,那么当前w = 31 > 30越界,所以直接进行剪枝,解空间树变成如下: 可扩展结点:E
9、; 活结点队列:F,G,J,K选择路径: A->B->EW:16P:45可扩展结点:F 活结点队列:G,J,K,L,M选择路径: A->C->FW:15P:25可扩展结点:G 活结点队列:J,K,L,M,N,O选择路径: A->C->GW:0P:0如果扩展J,那么当前w = 16+15=31>30,所以对J剪枝,解空间树变为:可扩展结点:K 活结点队列:L,M,N,O选择路径: A->B->E->K W:16 P:45可扩展结点:L 活结点队列:M,N,O选择路径: A->C-
10、>F->L W:30 P:50可扩展结点:M 活结点队列:N,O选择路径: A->C->F->MW:15P:25可扩展结点:N 活结点队列:O选择路径: A->C->G->N W:15 P:25可扩展结点:O 活结点队列:NULL选择路径: A->C->G->OW:0P:0活结点队列为空,算法终止,从可行解中筛选出最佳解为(0,1,1),maxP = 50;3.3 完整代码#include <iostream>using namespace std;/-template <c
11、lass Type>inline void Swap(Type &a,Type &b) Type temp = a; a = b; b = temp;template<class Type>void BubbleSort(Type a,int n) /记录一次遍历中是否有元素的交换 bool exchange; for(int i=0; i<n-1;i+) exchange = false ; for(int j=i+1; j<=n-1; j+) if(aj<=aj-1) Swap(aj,aj-1); exchange = true; /如果
12、这次遍历没有元素的交换,那么排序结束 if(false = exchange) break ; /-class Object template<class Typew,class Typep> friend Typep Knapsack(Typep p,Typew w,Typew c,int n, int bestx);public: int operator <= (Object a) const return d>=a.d; private: int ID; float d; /单位重量价值;/-template<class Typew,class Typep
13、> class Knap;/返回最大价值,bestx返回最优解template<class Typew,class Typep>Typep Knapsack(Typep p,Typew w,Typew c,int n, int bestx) /初始化 Typew W = 0; /装包物品重量 Typep P = 0; /装包物品价值 /定义依单位重量价值排序的物品数组 Object *Q = new Objectn; for(int i=1; i<=n; i+) /单位重量价值数组 Qi-1.ID = i; Qi-1.d = 1.0*pi/wi; P += pi; W
14、+= wi; if(W<=c) return P;/所有物品装包 /依单位价值重量排序 BubbleSort(Q,n); /创建类Knap的数据成员 Knap<Typew,Typep> K; K.p = new Typepn+1; K.w = new Typewn+1; for(int i=1; i<=n; i+) K.pi = pQi-1.ID; K.wi = wQi-1.ID; K.cp = 0; K.cw = 0; K.c = c; K.n = n; /调用MaxKnapsack求问题的最优解 Typep bestp = K.MaxKnapsack(); for(
15、int j=1; j<=n; j+) bestxQj-1.ID = K.bestxj; delete Q; delete K.w; delete K.p; delete K.bestx; return bestp;template<class T>class MaxHeap public: MaxHeap(int MaxHeapSize = 10); MaxHeap() delete heap; int Size() const return CurrentSize; T Max() if (CurrentSize = 0) return heap1; MaxHeap<
16、T>& Insert(const T& x); MaxHeap<T>& DeleteMax(T& x); void Initialize(T a, int size, int ArraySize);private: int CurrentSize, MaxSize; T *heap; / element array;template<class T>MaxHeap<T>:MaxHeap(int MaxHeapSize) MaxSize = MaxHeapSize; heap = new TMaxSize+1; Curre
17、ntSize = 0;template<class T>MaxHeap<T>& MaxHeap<T>:Insert(const T& x) if(CurrentSize = MaxSize) cout<<"no space!"<<endl; return *this; / 寻找新元素x的位置 / i初始为新叶节点的位置,逐层向上,寻找最终位置 int i = +CurrentSize; while (i != 1 && x > heapi/2) / i不是根节点,且其值大于父节
18、点的值,需要继续调整 heapi = heapi/2; / 父节点下降 i /= 2; / 继续向上,搜寻正确位置 heapi = x; return *this;template<class T>MaxHeap<T>& MaxHeap<T>:DeleteMax(T& x) / Set x to max element and delete max element from heap. / check if heap is empty if(CurrentSize = 0) cout<<"Empty heap!"
19、;<<endl; return *this; x = heap1; / 删除最大元素 / 重整堆 T y = heapCurrentSize-; / 取最后一个节点,从根开始重整 / find place for y starting at root int i = 1, / current node of heap ci = 2; / child of i while (ci <= CurrentSize) / 使ci指向i的两个孩子中较大者 if(ci<CurrentSize && heapci < heapci+1) ci+; / y的值大于
20、等于孩子节点吗? if(y >= heapci) break; / 是,i就是y的正确位置,退出 / 否,需要继续向下,重整堆 heapi = heapci; / 大于父节点的孩子节点上升 i = ci; / 向下一层,继续搜索正确位置 ci *= 2; heapi = y; return *this;template<class T>void MaxHeap<T>:Initialize(T a, int size,int ArraySize) delete heap; heap = a; CurrentSize = size; MaxSize = ArraySi
21、ze; / 从最后一个内部节点开始,一直到根,对每个子树进行堆重整 for(int i = CurrentSize/2; i >= 1; i-) T y = heapi; / 子树根节点元素 / find place to put y int c = 2*i; / parent of c is target location for y while (c <= CurrentSize) / heapc should be larger sibling if (c < CurrentSize && heapc < heapc+1) c+; / can we
22、 put y in heapc/2? if (y >= heapc) break; / yes / no heapc/2 = heapc; / move child up c *= 2; / move down a level heapc/2 = y; /-class bbnode public: template<class Typew,class Typep> friend Typep Knapsack(Typep p,Typew w,Typew c,int n, int bestx); bbnode * parent; /指向父节点的指针 bool LChild; /左
23、儿子节点标识;template<class Typew,class Typep>class HeapNode public: operator Typep() const return uprofit; Typep uprofit, /节点的价值上界 profit; /节点所相应的价值 Typew weight; /节点所相应的重量 int level; /活节点在子集树中所处的层序号 bbnode *ptr; /指向活节点在子集中相应节点的指针;/-template<class Typew,class Typep>class Knap public: Typep Ma
24、xKnapsack(); MaxHeap<HeapNode<Typep,Typew> > *H; Typep Bound(int i); void AddLiveNode(Typep up,Typep cp,Typew cw,bool ch,int lev); bbnode *E; /指向扩展节点的指针 Typew c; /背包容量 int n; /物品数 Typew *w; /物品重量数组 Typep *p; /物品价值数组 Typew cw; /当前重量 Typep cp; /当前价值 int *bestx; /最优解;template<class Typew
25、,class Typep>Typep Knap<Typew,Typep>:Bound(int i) /计算节点所相应价值的上界 Typew cleft = c-cw; /剩余容量高 Typep b = cp; /价值上界 /以物品单位重量价值递减序装填剩余容量 while(i<=n && wi<=cleft) cleft -= wi; b += pi; i+; /装填剩余容量装满背包 if(i<=n) b += pi/wi*cleft; return b;/将一个活节点插入到子集树和优先队列中template<class Typew,c
26、lass Typep>void Knap<Typew,Typep>:AddLiveNode(Typep up,Typep cp,Typew cw,bool ch,int lev) bbnode *b = new bbnode; b->parent = E; b->LChild = ch; HeapNode<Typep,Typew> N; N.uprofit = up; N.profit = cp; N.weight = cw; N.level = lev; N.ptr = b; H->Insert(N);/优先队列式分支限界法,返回最大价值,be
27、stx返回最优解template<class Typew,class Typep>Typep Knap<Typew,Typep>:MaxKnapsack() H = new MaxHeap<HeapNode<Typep,Typew> >(1000); /为bestx分配存储空间 bestx = new intn+1; /初始化 int i = 1; E = 0; cw = cp = 0; Typep bestp = 0;/当前最优值 Typep up = Bound(1); /价值上界 /搜索子集空间树 while(i!=n+1) /检查当前扩展
28、节点的左儿子节点 Typew wt = cw + wi; if(wt <= c) /左儿子节点为可行节点 if(cp+pi>bestp) bestp = cp + pi; AddLiveNode(up,cp+pi,cw+wi,true,i+1); up = Bound(i+1); /检查当前扩展节点的右儿子节点 if(up>=bestp) /右子树可能含有最优解 AddLiveNode(up,cp,cw,false,i+1); /取下一扩展节点 HeapNode<Typep,Typew> N; H->DeleteMax(N); E = N.ptr; cw =
29、 N.weight; cp = N.profit; up = N.uprofit; i = N.level; /构造当前最优解 for(int j=n; j>0; j-) bestxj = E->LChild; E = E->parent; return cp;/-int main() int n = 3; /物品数 int c = 30; /背包容量 int p = 0,45,25,25; /物品价值 下标从1开始 int w = 0,16,15,15; /物品重量 下标从1开始 int bestx4; /最优解 cout<<"背包容量为:"<<c<<endl; cout<<"物品重量和价值分别为:"<<endl; for(int i=1; i<=n; i+) cout<<"("<<wi<<","<<pi<<") " co
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- (2025年)中级粮油保管员培训复习题解析及答案
- 基于动物话题的初中英语七年级下册跨学科听说整合教学方案
- 初中八年级英语下册 Unit 8 文学作品阅读与主题意义探究单元整体教学方案
- 排水沟工程施工方案
- 幼儿园节日主题活动及健康安全方案
- 10KV供配电工程施工组织方案
- 科技企业保密管理制度
- 物业小区公共区域管理制度
- 市场营销活动策划制度
- 会计坚定信念工作方案
- 行车工考试题库及答案
- 2025内蒙古能源集团智慧运维公司运维人员社会招聘105人笔试参考题库附带答案详解
- 2026年中考数学压轴题专项练习-阿基米德折弦定理(学生版+名师详解版)
- 电影欣赏社团课件
- 2025年辽宁省交通高等专科学校单招职业技能考试试题及答案解析
- 2025年凉山州中考语文试题答案解析卷
- 《智慧物流概论》试卷及答案 共2套
- 税务讲解社保费课件
- T/CI 467-2024复合集流体(铜箔)
- 《赤壁之战》课本剧剧本:感受三国英雄的壮志豪情
- T-CPI 11029-2024 核桃壳滤料标准规范
评论
0/150
提交评论