首页 > 其他分享 >BFS详解

BFS详解

时间:2024-05-14 13:52:42浏览次数:14  
标签:状态 int 边权 BFS 队列 详解 最优化

BFS

在最优性问题中,状态按照非最优化属性进行分组,且每个分组存在且只需要保留最优状态。

一般最优性问题分为 \(2\) 种,边权为正数、边权为非负数。

边权为正数且相同

这种情况,转移时最优化属性的值会变得更劣,每次转移时最优化属性的值会变劣最小单位。

而最优化属性有拓扑序,可以按照拓扑序进行搜索,由优到劣对每层的状态进行搜索。在这种问题中每个分组中首次被搜到的状态就是最优的,之后的同组状态都可以忽略不计,可以用 BFS 逐层对状态进行处理,如图:

标红的点即为每个分组的最优状态,可用队列实现。

边权为非负数

转移时最优化属性的值不会变得更优。

这种情况是在上一种情况上增添了同一层连边的情况,发先这时没有拓扑序。

这时我们可以改动 BFS,先将同层的转移处理完,在处理后面层的转移,同样,每个分组中首次被处理的状态就是最优的,之后的同组状态都可以忽略。

如果拓展出同层状态就插入队头,否则插到队尾,所以我们需要一个双端队列。

边权为非负数但不同

记边权值域为 \(V\),那么我们可以开 \(V\) 个队列用并查集维护第一个不为空的队列进行拓展,发现这东西就是最短路,而用并查集维护其实就是堆找最小值,这种方法时间复杂度跟 Dij 没有太大差距,但空间巨大。

upd:并查集路压缩径加按秩合并后复杂度好似更优。

写法

  • BFS有两种写法:

    1.每产生一个状态就将它加入队列,在处理状态时判断是否可能是最优的。

    2.每产生一个状态先判断是否可能是最优的,再加入队列。

第一种方法适用面更广,但时间复杂度会更高,有些题用第二种方法会简便些,但有些题只能用第一种方法。

题目

P1443 马的遍历

首先先确定状态,\((x,y,t)\) 为走到格子 \(x,y\) 的时间为 \(t\),发现最优化属性为 \(t\),所以根据非最优化属性进行分组,将 \(x,y\) 相同的状态分为一组,其移动为转移,即为变劣最小单位,可用广搜实现。

第二种写法标准代码:

# include <bits/stdc++.h>

using namespace std;

const int N = 405;
const int kD[][2] = {{-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {-2, -1}, {-2, 1}, {2, -1}, {2, 1}};  

struct node {
  int x, y;
} q[N * N]; 

int d[N][N], n, m, x, y, h = 1, t;  

void Record (int x, int y, int v) {//广搜习惯在这里写一个Record函数来处理新状态                  
  if (x < 1 || x > n || y < 1 || y > m || d[x][y]) { 
    return;                                          
  }
  d[x][y] = v;   
  q[++ t] = {x, y};  
}

int main() {
  cin >> n >> m >> x >> y;
  for (Record(x, y, 1); h <= t; h ++) {                                     
    for (int i = 0; i < 8; i ++) {                                          
      Record(q[h].x + kD[i][0], q[h].y + kD[i][1], d[q[h].x][q[h].y] + 1);  
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      cout << setw(5) << d[i][j] - 1;
    }
    cout << "\n";
  }
  return 0;
}

标签:状态,int,边权,BFS,队列,详解,最优化
From: https://www.cnblogs.com/Livedreamyhy/p/18191161

相关文章

  • 机器学习策略篇:详解为什么是人的表现?(Why human-level performance?)
    为什么是人的表现?在过去的几年里,更多的机器学习团队一直在讨论如何比较机器学习系统和人类的表现,为什么呢?认为有两个主要原因,首先是因为深度学习系统的进步,机器学习算法突然变得更好了。在许多机器学习的应用领域已经开始见到算法已经可以威胁到人类的表现了。其次,事实证明,当试......
  • NumPy 数组复制与视图详解
    NumPy数组的复制与视图NumPy数组的复制和视图是两种不同的方式来创建新数组,它们之间存在着重要的区别。复制复制会创建一个包含原始数组相同元素的新数组,但这两个数组拥有独立的内存空间。这意味着对复制进行的任何更改都不会影响原始数组,反之亦然。创建副本可以使用以下方......
  • (MEGA详解)Memory enhanced global-local aggregation for video object detection (CVPR
    在视频中检测物体和在图像中检测物体的最大区别在于:信息存在于时间维度中。视频中孤立的帧可能会出现运动模糊、遮挡或失焦等问题,自然可以想到从整个视频中寻找线索来识别物体。当我们无法确定一个目标的类别时,我们会从其它帧中寻找一个与当前目标具有高度语义相似性的独特目标,并......
  • Oracle中pivot函数详解
    【基本介绍】【格式】:pivot(聚合函数for需要转为列的字段名in(需要转为列的字段值))【说明】:实现将指定字段的字段值转换为列的效果。【环境】:如下图是样例展示所使用的oracle版本。  【准备样例数据】样例数据如下图所示:NAME-学生姓名,SUBJECT-考试科目,GRADES-考试成......
  • Pyqt6&Pyside6 信号与槽详解
    信号与槽对于可视化编程,需要将界面上的控件有机结合起来,实现控件功能的联动和交互操作。比如点击按钮,实现某项功能。对按钮功能的定义,是通过信号(signal)与槽(slot)机制实现的。信号与槽是PySide6编程的基础,也是Qt的一大创新,有了信号与槽的编程机制,在PySide6中处理界面上各个控件......
  • ASH日志报告详解
    本文转自:https://blog.csdn.net/cuiyan1982/article/details/778145341.ASH日志报告详解1.1ASH报告使用ash报告,在生成ash报告之后,可以重新检索哪些标识为短暂性能问题的信息。ash报告的内容分成了以下几个部分:topeventsloadprofiletopsqltoppl/sqltopjavatopses......
  • HTTP 连接详解
    概述世界上几乎所有的HTTP通信都是由TCP/IP承载的,客户端可以打开一条TCP/IP连接,连接到任何地方的服务器。一旦连接建立,客户端和服务器之间交换的报文就永远不会丢失、受损或失序TCP(TransmissionControlProtocol)传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层......
  • 详解Redis持久化(持久化高危漏洞利用与多种对抗方案、RDB、AOF、同步手动持久化、异步
    谨防持久化+未授权访问漏洞入侵服务器CVE编号找不到,CNVD有一个:CNVD-2015-07557(国家信息安全漏洞共享平台漏洞编号)。这是我之前写过的文章,漏洞成因、影响范围、POC与对抗方案有详解:谨防利用Redis未授权访问漏洞入侵服务器RDB(RedisDatabase、全量保存,默认方式)极简概括:通过符......
  • set 容器详解 附大根堆题解
    声明本文中题解部分内容大部分转载自@sonnety的这篇博客中,本文为为方便复习而写的结论类文章,读者可自行跳转至原文处阅读。PART1set什么是set——来源cppreference简言之,它就是一种存进去就可以自动按升序排列的特殊容器,通常的set还具有自动去重的功能。定义方......
  • 4-LVS命令详解
    4.LVS命令详解集群定义一组通过高速网络互联的计算机,以单一系统的模式加以管理;将很多服务器集中起来一起,提供同一种服务,在客户端看起来就像是只有一个服务器,可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收益目的、优点提高性能、降低成本、提高可扩......