主讲人: 吕敏 Email: { lvmin05@ustc.edu.cn } Spring 2016,USTC 算法基础 主讲人: 吕敏 Email: { lvmin05@ustc.edu.cn } Spring 2016,USTC.

Slides:



Advertisements
Similar presentations
渡黑水溝 郁永河. 2 戎克船:是明末清初時期往返兩岸的主要交通工具 ∗ 1. 關於台灣的開發歷史,我們到底了解多少呢?不妨試著說出 就我們所知有關台灣開發史的故事、小說、電影、音樂與大 家分享。 ∗ 2. 什麼是黑水溝?黑水溝為什麼會成為大陸移民渡海來臺時最 大的威脅? ∗ 3. 有聽過「六死三留一回頭」、「有唐山公,無唐山嬤」這兩.
Advertisements

教務處註冊組 /7 (二) 10 : 00 至 15 : 00 止 ★ 6/8 彙整報名資料後, 6/9 向高中承 辦學校報名 ★ 因校內作業時間緊迫,逾時恕不 受理。 校內報名時間.
单元二:面向对象程序设计 任务二:借书卡程序设计.
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
科学就医健康教育核心信息 健康中国行·科学就医 一、倡导科学就医 二、遵从分级诊疗 三、定期健康体检 四、鼓励预约挂号 五、就医注意事项
三水区安监局 企业安全用电 2013年4月.
★中国近代史: 1840年————1949年 鸦片战争 新中国诞生 ★历史线索: 1、资本主义列强对中国的侵略 2、中国人民的反抗和探索:
项目6 通用堆栈.
企业价值收益法评估 ----财务报表调整 主讲人:阮咏华 1.
广西师范大学教科院马佳宏 电 话 0773- (O) 高校教师资格认定考试的若干事项 广西师范大学教科院马佳宏 电 话 0773- (O)
司法体制改革与律师执业前景瞻望 黄太云
迴圈 迴圈基本觀念 while迴圈 do 迴圈 for迴圈 巢狀迴圈 迴圈設計注意事項 其他控制指令 迴圈與選擇的組合.
苟利国家生死以, 岂因祸福避趋之。 ----禁毒英雄,一生为公 --林则徐.
职 业 礼 仪 讲师:刘巍女士.
第5章 回溯法 欢迎辞.
李建民 教授 北京百川健康科学研究院 脊柱健康技术研究中心
學校:光春國中 班級:七年三班 製作團隊: 顏序芳 李邰岳 謝宜軒
AI人工智慧報告 黑白棋 班級:資工四乙 學號:498G0009 姓名:盧冠妤.
南京理工大学 第2章 Java基本语法 本章我们将学习Java编程语言的基本语法,包括变量、操作符、表达式、语句、字符串、数组、控制流以及如何使用帮助文档。 使用下面的编程框架: public class Test{ public static void main(String []args){ //以下添加测试代码.
三大自然区的内部差异 地理 全日制普通高级中学教科书(选修) 第二册 人民教育出版社地理社会室 编著 人民教育出版社 关于.
第六章 分支限界法.
贴近教学 服务师生 方便老师.
上課囉 職場甘苦談 小資男孩向錢衝 育碁數位科技 呂宗益/副理.
设计模式可以帮助我们改善系统的设计,增强 系统的健壮性、可扩展性,为以后铺平道路。
第 5 章 流程控制 (一): 條件分支.
第5章 回溯法 “通用的解题法” 欢迎辞.
第二章 JAVA语言基础.
授課大綱 第一章 緒 論 第一節 應用文的意義 第二節 應用文的種類 第二章 書 信 第一節 書信的種類 第二節 書信的結構 第三章 便 條
第三章 控制结构.
哈夫曼编码.
JAVA程序设计 第5章 深入理解JAVA语言----补充.
程式設計實作.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
程序设计期末复习 黎金宁
程式撰寫流程.
新觀念的 VB6 教本 第 6 章 資料型別.
2019/1/17 Java语言程序设计-程序流程 教师:段鹏飞.
中间代码生成.
主讲人: 吕敏 { } Spring 2016 ,USTC 算法基础 主讲人: 吕敏 { } Spring 2016 ,USTC.
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
第六章 分支限界法 理解分支限界法的剪枝搜索策略。 掌握分支限界法的算法框架 队列式(FIFO)分支限界法 优先队列式分支限界法.
山东师范大学信息科学与工程学院软件工程研究所 徐连诚 2006年11月20日
第5章 回溯法 欢迎辞.
中華大學 資訊工程學系 報告人:資訊工程學系 許慶賢 系主任.
Lucene 算法介绍 IR-Lab 胡晓光.
程式的時間與空間 Time and Space in Programming
如何检索统计申请与在研项目(科研人员) “科研之友”技术支持小组
Disjoint Sets Michael Tsai 2013/05/14.
第二章 Java语法基础.
新竹縣108學年度第1次國小以上 特殊教育鑑定安置說明會
進修學院與我.
本节内容 Lua基本语法.
第7章 概率算法 欢迎辞.
目标 流程控制 字符串处理 C# 的类和对象 C# 访问修饰符 C# 构造函数和析构函数.
第三章 贪心方法 (Greedy Technique)
第八节 算术运算符和算术表达式.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
慈惠醫護管理專科學校圖書館 館際合作使用方法.
第二章 Java基本语法 讲师:复凡.
第1章 数据结构基础概论 本章主要介绍以下内容 数据结构研究的主要内容 数据结构中涉及的基本概念 算法的概念、描述方法以及评价标准.
硬幣遊戲解題詳解 王豐緒 銘傳大學資訊工程學系.
本章主題 C++的程式結構 資料型態與宣告 算術運算 簡易的輸入輸出指令 程式編譯(Compile)的過程與原理.
“上海市教师教育课程资源共享管理平台” 学分银行操作指南
第2章 Java语言基础.
判斷(選擇性敘述) if if else else if 條件運算子.
三、 动量和角动量 1 、 质点动量定理 动量 冲量.
第二章 Java基础语法 北京传智播客教育
第二章 Java基本语法 讲师:复凡.
第六章 直接成本法.
Presentation transcript:

主讲人: 吕敏 Email: { lvmin05@ustc.edu.cn } Spring 2016,USTC 算法基础 主讲人: 吕敏 Email: { lvmin05@ustc.edu.cn } Spring 2016,USTC

第十二讲 分支限界法 内容提要: 理解分支限界法的剪枝搜索策略 掌握分支限界法的算法框架 通过应用范例学习分支限界法的设计策略 第十二讲 分支限界法 内容提要: 理解分支限界法的剪枝搜索策略 掌握分支限界法的算法框架 (1)队列式(FIFO)分支限界法 (2)优先队列式分支限界法 通过应用范例学习分支限界法的设计策略 2019/5/28

方法概述 与回溯法区别: 求解目标不同: 搜索方法不同: 对扩展结点的扩展方式不同: 存储空间的要求不同 一般而言,回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是尽快地找出满足约束条件的一个解; 搜索方法不同: 回溯法使用深度优先方法搜索,而分支限界一般用宽度优先或最佳优先方法来搜索; 对扩展结点的扩展方式不同: 分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点; 存储空间的要求不同 分支限界法的存储空间比回溯法大得多,因此当内存容量有限时,回溯法成功的可能性更大。 2019/5/28

方法概述 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。对已处理的各结点根据限界函数估算目标函数的可能取值, 基本思想: 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。对已处理的各结点根据限界函数估算目标函数的可能取值, 选取使目标函数取得极大(小)值的结点优先进行广度优先搜索 不断调整搜索方向,尽快找到解 , 裁剪那些不能得到最优解的子树以提高搜索效率。 特点:限界函数常基于问题的目标函数,适用于求解最优化问题。 2019/5/28

方法概述 搜索策略: 在扩展结点处,生成其所有的子结点(分支), 从当前的活结点表中选择下一个扩展结点。 在每一活结点处,计算一个函数值(优先值), 根据这些函数值,从当前活结点表中选择一个最有利的结点作为扩展结点, 目的:搜索朝有最优解的分支推进,尽快地找出一个最优解。 为了有效地选择下一个扩展结点,以加速搜索的进程

方法概述 求解步骤: 定义解空间(对解编码); 确定解空间的树结构; 按BFS等方式搜索: a. 每个活结点仅有一次机会变成扩展结点; c. 在新结点中,删除不可能导出最优解的结点;//限界策略 d. 将剩余的新结点加入活动表(队列)中; e. 从活动表中选择结点再扩展; //分支策略 f. 直至活动表为空; 2019/5/28

方法概述 常见的两种分支限界法: 队列式(FIFO)分支限界法:从活结点表中取出结点的顺序与加入结点的顺序相同,因此活结点表的性质与队列相同; 与宽度优先搜索类似,只是不搜索以不可行结点(已经被判定不能导致可行解或不能导致最优解的结点)为根的子树。 优先队列(代价最小或效益最大)分支限界法:每个结点都有一个对应的耗费或收益,以此决定结点的优先级: 如果查找一个具有最小耗费的解,则活结点可用小根堆来建立,下一个扩展结点就是具有最小耗费的活结点; 如果希望搜索一个具有最大收益的解,则可用大根堆来构造活结点表,下一个扩展结点是具有最大收益的活结点。 2019/5/28

解空间树的动态搜索 (1)回溯求解0/1背包问题,虽剪枝减少了搜索空间,但整个搜索按深度优先机械进行,是盲目搜索(不可预测本结点以下的结点进行的如何)。 (2)回溯求解TSP也是盲目的(虽有目标函数,也只有找到一个可行解后才有意义)

解空间树的动态搜索 分支限界法首先确定一个合理的限界函数,并根据限界函数确定目标函数的界[down, up]; 如果某孩子结点的目标函数值超出目标函数的界,则将其丢弃(从此结点生成的解不会比目前已得的更好),否则入待处理表。

0-1背包问题 物品数量n=3,重量w=(20,15,15),价值v=(40,25,25),背包容量c=30,试装入价值和最大的物品? FIFO队列分支限界法求解: 解空间:{(0,0,0),(0,0,1),…,(1,1,1)} 解空间树: 2019/5/28

0-1背包问题 BFS搜索(FIFO队列) 2019/5/28

0-1背包问题 优先队列分支限界法求解: 解空间:{(0,0,0),(0,0,1),…,(1,1,1)} 解空间树: 2019/5/28

0-1背包问题 BFS搜索(优先队列:按照价值率优先) 2019/5/28

0-1背包问题 总结: 与回溯法相比,分支限界法 可根据限界函数不断调整搜索方向, 选择最可能得最优解的子树优先进行搜索找到问题的解。

0-1背包问题 算法思想: 首先,要对输入数据进行预处理,将各物品依其单位重量价值从大到小进行排列。 在下面描述的优先队列分支限界法中,节点的优先级由已装袋的物品价值加上剩下的最大单位重量价值的物品装满剩余容量的价值和。 算法首先检查当前扩展结点的左儿子结点的可行性。如果该左儿子结点是可行结点,则将它加入到子集树和活结点优先队列中。当前扩展结点的右儿子结点一定是可行结点,仅当右儿子结点满足上界约束时才将它加入子集树和活结点优先队列。当扩展到叶节点时为问题的最优值。 2019/5/28

0-1背包问题 MaxKnapsack( n, c, w[ ], p[ ] ) { //优先队列式分支限界法,返回最大价值,n为物品数目,c为背包容量,w为物品重量,p为物品价值 //算法开始之前,已经按照物品单位价值率按照降序顺序排列好了 cw = 0, cp = 0; //cw为当前装包重量,cp为当前装包价值 bestp = 0; //当前最优值 i=1, up = Bound(1) ; //函数Bound(i)计算当前结点相应的价值上界 while( i != n+1 ) { //非叶子结点 //首先检查当前扩展结点的左儿子结点为可行结点 if( cw + w[i] <= c ) { //左孩子结点为可行结点 if( cp + p[i] > 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); //将右孩子结点插入到优先队列中 //从优先级队列(堆数据结构)中取下一个扩展结点N H->DeleteMax( N) ; i = N.level; 分支限界搜索过程 2019/5/28

0-1背包问题 { //计算结点所对应的价值的上界 cleft = c – cw; //剩余背包容量 b = cp; //价值上界 Bound( i ) { //计算结点所对应的价值的上界 cleft = c – cw; //剩余背包容量 b = cp; //价值上界 //以物品单位重量价值递减顺序装填剩余容量 while( i <= n && w[i] <= cleft ){ cleft -= w[i]; //w[i]表示i物品的重量 b += p[i]; //p[i]表示i物品的价值 i++; } //装填剩余容量装满背包 if( i<=n) b += p[i]/w[i] * cleft; return b; 2019/5/28

分支限界法的设计思路 设求解最大化问题,解向量为X=(x1,…,xn),xi的取值范围为Si,|Si|=ri。在使用分支限界搜索问题的解空间树时,先根据限界函数估算目标函数的界[down, up],然后从根结点出发,扩展根结点的r1个孩子结点,从而构成分量x1的r1种可能的取值方式。 对这r1个孩子结点分别估算可能的目标函数bound(x1),其含义:以该结点为根的子树所有可能的取值不大于bound(x1),即: bound(x1)≥bound(x1,x2)≥…≥ bound(x1,…,xn)

分支限界法的设计思路 若某孩子结点的目标函数值超出目标函数的下界,则将该孩子结点丢弃;否则,将该孩子结点保存在待处理结点表PT中。 直到一个叶子结点时的可行解X=(x1,…,xn),及目标函数值bound(x1,…,xn)。

单源最短路径问题 问题描述: 下面以一个例子来说明单源最短路径问题:在下图所给的有向图G中,每一边都有一个非负边权。要求图G的从源顶点s到目标顶点t之间的最短路径。 2019/5/28

单源最短路径问题 解空间树: 下图是用优先队列式分支限界法解有向图G的单源最短路径问题产生的解空间树。其中,每一个结点旁边的数字表示该结点所对应的当前路长。 2019/5/28

单源最短路径问题 算法思想: 用极小堆来存储活结点表 其优先级是结点所对应的当前路长 算法 从图G的源顶点s和空优先队列开始。 从堆中取出具有最小当前路长的结点作为当前扩展结点,并依次检查与当前扩展结点相邻的所有顶点。 如果从当前扩展结点i到顶点j有边可达,且从源出发,途经顶点i再到顶点j的所相应的路径的长度小于当前最优路径长度,则将该顶点作为活结点插入到活结点优先队列中。 扩展过程一直继续到活结点优先队列为空时为止。 2019/5/28

单源最短路径问题 剪枝策略: 在算法扩展结点的过程中,一旦发现一个结点的下界不小于当前找到的最短路长,则算法剪去以该结点为根的子树。 在算法中,利用结点间的控制关系进行剪枝。从源顶点s出发,2条不同路径到达图G的同一顶点。由于两条路径的路长不同,因此可以将路长长的路径所对应的树中的结点为根的子树剪去。 2019/5/28

单源最短路径问题 经过不同的路径到达相同的顶点 B A A优于B,B可剪枝 2019/5/28

单源最短路径问题 算法代码: while (true) { // 搜索问题的解空间, //while循环体完成对解空间内部结点的扩展 for (int j=1;j<=n;j++) if(a[enode.i][j] <Float.MAX_VALUE && enode.length+a[enode.i][j] < dist[j]) { // 顶点i到顶点j可达,且满足控制约束, dist[j]=enode.length+a[enode.i][j]; p[j]=enode.i; HeapNode node = new HeapNode(j,dist[j]); heap.put(node); //加入活结点优先队列 } if (heap.isEmpty()) break; else enode = (HeapNode) heap.removeMin(); 2019/5/28

单源最短路径问题 Dijakstra算法和分支限法在解决该问题的异同: Dijakstra算法:每一步的选择为当前步的最优,复杂度为O(n2)。 分支限算法:每一步的扩散为当前耗散度的最优。 复杂度通常更大.

装载问题 问题描述: 有一批共n个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱i的重量为Wi,且 装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船。如果有,找出一种装载方案。 容易证明:如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。 (1)首先将第一艘轮船尽可能装满; (2)将剩余的集装箱装上第二艘轮船。 2019/5/28

装载问题 将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近。由此可知,装载问题等价于以下特殊的0-1背包问题。 2019/5/28

装载问题 队列式分支限界法 在算法的while循环中,首先检测当前扩展结点的左儿子结点是否为可行结点。如果是则将其加入到活结点队列中。然后将其右儿子结点加入到活结点队列中(右儿子结点一定是可行结点)。2个儿子结点都产生后,当前扩展结点被舍弃。 活结点队列中的队首元素被取出作为当前扩展结点,由于队列中每一层结点之后都有一个尾部标记-1,故在取队首元素时,活结点队列一定不空。当取出的元素是-1时,再判断当前队列是否为空。如果队列非空,则将尾部标记-1加入活结点队列,算法开始处理下一层的活结点。 2019/5/28

装载问题 代码: while (true) { if (ew + w[i] <= c) // 检查左儿子结点, w[i]=1, ew存储当前扩展结点相应的载重量 enQueue( ew + w[i], i ); enQueue(ew, i); //右儿子结点总是可行的 ew = ((Integer) queue.remove()).intValue(); // 取下一扩展结点 if (ew == -1) //如果是本层的结尾结点 { if (queue.isEmpty()) return bestw; queue.put(new Integer(-1)); // 同层结点尾部标志 ew = ((Integer) queue.remove()).intValue(); // 取下一扩展结点 i ++; // 进入下一层 } 2019/5/28

装载问题 算法改进 节点的左子树表示将此集装箱装上船,右子树表示不将此集装箱装上船。设bestw是当前最优解;ew是当前扩展结点所相应的重量;r是剩余集装箱的重量。则当ew+rbestw时,可将其右子树剪去,因为此时若要船装最多集装箱,就应该把此箱装上船。 另外,为了确保右子树成功剪枝,应该在算法每一次进入左子树的时候更新bestw的值。 2019/5/28

装载问题 // 检查左儿子结点 int wt = ew + w[i]; if (wt <= c) { // 可行结点 右儿子剪枝 // 检查左儿子结点 int wt = ew + w[i]; if (wt <= c) { // 可行结点 if (wt > bestw) bestw = wt; // 加入活结点队列 if (i < n) queue.put(new Integer(wt)); } 提前更新bestw // 检查右儿子结点 if (ew + r > bestw && i < n) // 可能含最优解 queue.put(new Integer(ew)); ew=((Integer)queue.remove()).intValue(); // 取下一扩展结点 2019/5/28

装载问题 构造最优解 为了在算法结束后能方便地构造出与最优值相应的最优解,算法必须存储相应子集树中从活结点到根结点的路径。为此目的,可在每个结点处设置指向其父结点的指针,并设置左、右儿子标志。找到最优值后,可以根据parent回溯到根节点,找到最优解。 private static class QNode { QNode parent; //父结点 boolean leftChild; //左儿子标志 int weight; //结点所相应的载重量 } for (int j = n; j > 0; j--) { bestx[j] = (e.leftChild) ? 1 : 0; e = e.parent; } 2019/5/28

装载问题 优先队列式分支限界法 解装载问题的优先队列式分支限界法用最大优先队列存储活结点表。活结点x在优先队列中的优先级定义为从根结点到结点x的路径所相应的载重量再加上剩余集装箱的重量之和。 优先队列中优先级最大的活结点成为下一个扩展结点。以结点x为根的子树中所有结点相应的路径的载重量不超过它的优先级。子集树中叶结点所相应的载重量与其优先级相同。 在优先队列式分支限界法中,一旦有一个叶结点成为当前扩展结点,则可以断言该叶结点所相应的解即为最优解。此时可终止算法。 2019/5/28

设计一个算法,计算最佳工作分配方案,使总费用达到最小。 作业 : 设有n件工作分配给n个人。将工作j分配给第i个人所需的费用为cij。试设计一个算法,为每个人都分配1件不同的工作,并使总费用达到最小。 设计一个算法,计算最佳工作分配方案,使总费用达到最小。 2019/5/28