第六章——分枝限界法

这篇具有很好参考价值的文章主要介绍了第六章——分枝限界法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

分枝限界法概述

分枝限界法和回溯法一样,也是一种在问题的解空间树上搜可行解的穷举算法。

其中“分枝”指的是“分枝限界法”搜索可行解采用的策略为广度优先搜索或实现方法和思路类似的代价优先搜索。

广度优先搜索的概念和实现前面已经介绍过很多次了,这里不再做赘述;代价优先搜索的目的是以某种定义下的优先级,按照优先级从高到低的顺序处理所有的结点。

(从低到高和从高到低本质上是一样的,这里以从高到低为例)。

如果状态结点能够按照优先级不严格(可以相等)降低的顺序,在解空间树上按照结点高度从高到低,同高度结点从左到右或从右到左的排列,那我们可以用广度优先搜索来达到代价优先搜索的目的(广度优先搜索的搜索顺序和代价优先搜索的搜素顺序相同)。

但是状态空间树上的状态结点是通过决策联系起来的,决策对于状态优先级相关的属性的变化多样(可能增大,可能减小,可能线性,可能非线性),状态结点按照优先级从高到低的顺序在状态空间树上的出现往往会是跳跃式的,与解空间树的结构无关。

如果策略能够始终保持状态结点到子节点优先级相关的属性递增或递减(即树上的结点从属性数值的角度来看符合堆的性质),我们可以在代价优先搜索中用堆数据结构来存储状态空间中未处理过的结点,处理节点过程中根据可选策略扩展结点加入容器的方法和广度优先搜索相同。

根据堆数据结构的性质,我们每次取堆顶(队首)结点进行处理,即是剩余未处理结点中优先级最高的结点(未加入容器的子孙节点,容器中一定存在一个结点的优先级高于该子孙节点的优先级,所以是未处理中结点中优先级最高的结点),这样一直处理即是按照优先级最高到低的顺序处理所有的状态节点。

(具体原因和用反证法证明,不做赘述)。

“限界”指的是限界函数,和回溯法中的限界函数一样,在广度(代价)优先搜索将被扩展的结点加入到(优先)队列中时,删除掉一些不必要的子节点,从而将选择变得更有效以加速搜索的进程。

个人归纳认为:回溯法=(状态空间树上的)一般深度优先搜索+限界函数,分枝限界法=(状态空间树上的)一般广度(代价)优先搜索+限界函数。

作为两种在状态空间书上搜索可行解的算法,我们一般考虑状态空间树的宽度和深度来选择使用回溯法还是分枝限界法:存在根节点到部分叶子结点的路径过长时,选择分枝限界法避免进入某条过长路径的搜索;如果可选择的决策过多,即树的宽度过大时,选择回溯法来避免扩展状态空间树同一高度过多的状态节点。

如果两种情况同时存在,可以采取限定单次回溯法搜素最大深度的方法来避免回溯法搜素进入过深的分支,不断扩大单次回溯法搜素的最大深度直到某次的回溯法寻找到可行解为止,这种策略称为迭代加深。

如果状态节点的属性满足代价优先搜索的要求,即子节点的优先级都高于父节点的优先级,我们也可以用分枝限界法去寻找特定意义上的最优解。

如果属性值(优先级)按照层次从上到下递减且最优解的“优”指的就是按照层次从上到下递减的优先级,那么以代价优先搜索为模板搜素到的第一个可行解即为我们的最优解,在这种问题背景下不需要进行与当前最优解比较判断能否得到更优解的剪枝函数。

确定可行解(最优解)所进行的决策

即在图(树)的搜索问题中,求解根结点到当前结点的路径,一般有两种通用的策略:

第一种是对每个节点保存根节点到该节点的路径,在扩展时通过根结点到父节点的路径获得根结点到子节点的路径。

这种方法实现起来简单,但是往往会浪费空间和时间。

第二种是在扩展子节点时对每个结点保存它在状态空间上的前驱节点,即父节点,然后通过对父节点的回溯得到该节点到根节点的路径,逆序即是根节点到该节点的路径。

分枝限界法的时间性能

分枝限界法和回溯法本质上都属于穷举法(广度优先搜索和深度优先搜索),在最坏情况下与穷举法的复杂度相同(甚至更糟,因为需要进行限界值的计算和限界函数的判断),实际求解效率基本上由限界函数决定。


求解0/1背包问题

即前面介绍过很多遍的0/1背包问题。

重量小于规定重量的结点通过决策构成解空间树,由于0/1背包问题的决策保证子节点中的价值属性一定大于等于父节点的价值属性,结点的价值属性用于确定结点的优先级,我们可以通过优先队列式分枝限界法,即以代价优先搜索为模板的分枝限界法求解0/1背包问题的最优解。

代价预先搜索求解0/1背包问题,就是在解空间树上以状态节点的价值属性作为优先级高度的标准进行上的代价优先搜索。

限界函数中的左孩子剪枝策略与回溯法中的左孩子剪枝策略一致;上一章节中提到0/1背包的右孩子剪枝相当于固定右子节点后续的策略向左,即将所有还没有选择的物品加入背包来得到一个价值的上界。

实际上这种价值上界的估计是比较粗糙的,因为剩余的物品我们往往无法全部加入到当前的背包中。这种上界估计的方式就相当于固定策略跳跃到右子树最左边的状态节点,没有进行真正的搜索,实际上这个扩展得到的“最左边的状态节点”可能并不满足问题规范的条件,即不是一个满足要求的可行解(实际不存在于解空间树上),上界被估计得过高了。

那如果我们是通过实际搜索,搜索到右子树满足问题条件的最左状态节点呢?即课件上的原做法:

第六章——分枝限界法
这种价值上界的估计方法在重量小价值高的物品出现在解空间树下层的决策时会出现反例。解决的方案也很简单,就是避免重量小价值高的物品出现在解空间树的下层,或者说避免重量小价值高的物品在物品序列中出现在重量大价值小的物品之后,即对物品序列进行一个预处理:在进行分枝限界法之前,先按照“价值/重量”的值对物品序列进行从大到小的排序。

对应的队列式分枝限界法求解如下(只介绍一个框架,在能够使用代价优先搜索的情况下一般还是使用代价优先搜索):文章来源地址https://www.toymoban.com/news/detail-486977.html

//队列中的状态结点类型
struct NodeType{
   	
	int no;//结点编号
	int i;//当前结点在搜索空间中的层次
	int w;//搜素到当前结点的总重量
	int v;//搜素到当前结点的总价值
	int x[MAXN];//搜素到当前状态结点进行过的决策 
	double ub;//限界函数bound预估的价值上界
};
//计算状态结点e的价值上界
//需要对物品价值/重量的值进行一个排序
void bound(NodeType &e){
   
	//固定后续的决策向左,搜索右子树满足问题条件的最左状态节点
	int i=e.i+1;
	int sumw=e.w;
	double sumv=e.v;
	while ((sumw+w[i]<=W)&&i<=n){
   	
		sumw+=w[i];	sumv+=v[i];	i++;
	}
	//如果所有剩余的物品不能全部装入背包,对于不能完全装入背包的物品,采用分块极限的方式估计价值上界 
	if (i<=n) e.ub=sumv+(W-sumw)*v[i]/w[i];
	//如果所有剩余的物品都能装入背包 
	else e.ub=sumv;
}
//将结点加入容器并通过结点的层次判断可行解,通过比较得到最优解 
void EnQueue(NodeType e,queue<NodeType> &qu){
   
	//通过结点的层次判断可行解
	if (e.i==n){
   
		if (e.v>maxv){
   
			//保存最优解的信息 
			maxv=e.v;
			for (int j=1;j<=n;j++) bestx[j]=e.x[j];
		}
	}
	else qu.push(e);//非叶子结点进队
}
//队列式分枝限界法求0/1背包的最优解
void bfs(<

到了这里,关于第六章——分枝限界法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 01背包(动态规划,贪心算法,回溯法,分支限界法)

    有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? number=4,capacity=8 物品编号(i) W(体积) V(价值) 1 2 3 2 3 4 3 4 5 4 5 6 1.什么是动态规划 1.动态规划算法是通过拆分问题,定义问题状态和状态之间的关系, 使得

    2024年02月08日
    浏览(68)
  • 最大团问题(MPP)之回溯法、分支限界法

    给定一个无向图 G = ( V , E ) G=(V, E) G = ( V , E ) , 其中 V V V 是图的顶点集, E E E 是图的边集: 完全子图:如果 U ⊆ V U⊆V U ⊆ V ,对任意的 u , v ∈ U u, v∈U u , v ∈ U , 有 ( u , v ) ∈ E (u, v)∈E ( u , v ) ∈ E , 则称 U U U 是 V V V 的完全子图 团: G G G 的完全子图 U U U 就是 G G G 的团。

    2024年02月07日
    浏览(40)
  • 回溯法,分支限界法,动态规划法求解0-1背包问题(c++)

    问题描述 给定n种物品和一背包。物品i的重量是wi0,其价值为vi0,背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 搜索空间: 子集树(完全二叉树) 约束函数(进包用): 如果当前背包中的物品总重量是cw,前面k-1件物品都已经决定是否进包,那

    2024年02月10日
    浏览(58)
  • 五种基础算法小结与典型题目分享(动态规划、分治、贪心、回溯、分支限界)

    动态规划是用于解决多阶段决策问题的算法策略。它通过用变量集合描述当前情境来定义“状态”,进而用这些状态表达每个阶段的决策。 每个阶段的状态是基于前面的状态经过某种决策得到的。通过建立状态间的递推关系,并将其形式化为数学递推式,得到“状态转移方程

    2024年01月19日
    浏览(65)
  • 【课设】java:迷宫小游戏(递归与分治、动态规划、贪心算法、回溯法、分支限界法)

    鱼弦:CSDN内容合伙人、CSDN新星导师、全栈领域优质创作者 、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen) 递归与分治算法 原理: 递归与分治算法将问题分解为子问题,递归地解决每个子问题,最后将结果合并得到整

    2024年02月02日
    浏览(39)
  • 第六章:SpringMVC上

    什么是 MVC MVC 是一种软件架构的思想,将软件按照模型、视图、控制器来划分。 M : Model ,模型层,指工程中的 JavaBean ,作用是处理数据。 一类称为实体类 Bean ,专门存储业务数据的。一类称为业务处理 Bean ,专门用于处理业务逻辑和数据访问。 V : View ,视图层,指工程

    2024年02月14日
    浏览(50)
  • Python第六章作业

    目录 第1关 列表的属性与方法 第2关 推导式与生成器 第3关 列表的合并与排序 第4关 二维列表排序 第5关 动物重量排序 第6关 身份证号升位 第7关 完美立方数 第8关 约瑟夫环问题 第9关 文本分析(2)——统计英文文件中的单词数 第1关 列表的属性与方法 初始化一个空

    2024年02月05日
    浏览(47)
  • 第六章 Linux 磁盘管理

    如果我们想在系统中增加一块硬盘用于数据存取,那么大概需要以下步骤: 目的,一是为了分割硬盘空间方便管理,更重要的是让各个分区都基本独立开来,这样如果某个区发生问题,至少不会直接影响到其他分区。 举例:如果把一块磁盘比喻成一大块地,那么对磁盘进行

    2024年02月04日
    浏览(56)
  • 第六章:string类

    string是字符序列的类 C++文档 C语言中,字符串是以’\\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。 ASCII (American S

    2024年02月17日
    浏览(51)
  • Scala(第六章 面向对象)

    1、 Scala的面向对象思想和Java的面向对象思想和概念是一致的。 2、Scala中语法和Java不同,补充了更多的功能。 1)基本语法 1 2)Scala包的三大作用(和Java一样) 1、区分相同名字的类 2、当类很多时,可以很好的管理类 3、控制访问范围 6.1.1 包的命名 1)命名规则 只能包含数

    2024年02月13日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包