第五十一章 BFS进阶(一)——双端队列广搜

news/2024/4/29 14:09:43/文章来源:https://blog.csdn.net/weixin_72060925/article/details/128960624

第五十一章 BFS进阶(一)——双端队列广搜

  • 一、原理
  • 二、例题
    • 1、问题
    • 2、分析
  • 三、代码

一、原理

在介绍双端队列广搜之前,我们先回顾一下堆优化版本的dijkstradijkstradijkstra算法。

在这个算法中,我们使用的是小根堆来找到距离起点的最小值。而这个最小值就是该点到起点的最短距离。然后我们再用这个最小值去松弛该点的临边。

如果临边松弛成功,就让这个点进入我们的优先队列。

今天所涉及到的双端队列广搜相当于一个特殊情况下的dijkstra算法。

我们先来剖析一下之前的朴素版本的BFS。

我们的朴素版本的BFS也用到了一个队列,只不过我们用的是普通队列。

那么这个队列有什么特殊的性质呢?

在这里插入图片描述
我们假设现在BFS到了红色线所在的层,那么假设第一个红色点出队,然后该红色点又更新了两个蓝色点,那么这两个点也会进队列。

那么我们就发现队列中的点是符合二段性的。

即前一段到原点的距离是x,后一段到原点的距离是x+1,不可能出现第三段。

因为如果出现了第三段,一定是从第二段的x+1扩展出来的。而轮到第二段出队的时候,第一段肯定早就出队了,此时队列中是第二段和第三段,依旧符合二段性。

那么这个二段性还有一个特殊的地方,它是距离小的一段在前面,距离大的一段在后面,这就符合了单调递增的性质。

因此,我们的队头就是最小的,也就是说在这种特殊的情况下, 我们的队列达到了和优先队列一样的效果。

那么知道了这个有什么用呢?

我们可以换一个角度,我们把第一段的x看作x+0。

此时,我们我们的图就不在是只存在边权为1的图,而是存在边权为1和0的图。

有了这个思路以后,我们再来模拟一下dijkstra的过程。

当队头出队的时候,此时是距离原点最近的点。假设这个最小距离是x,该点是A。

再给A设置几个邻接点:B,C,D。

这三个点到A的距离是0,1,0。

不妨让A点成功松弛这几个点,那么这几个点都会入队。

其中B到原点的距离就是x+0,C到原点的距离就是x+1,D到原点的距离就是x + 0

那么为了维护我们队列的二段性,我们就会把B和D点放到队列中的前半段,C放到队列中的后半段。

即从两边插入队列。

好,现在我们就发现,当一个图中存在只存在两个非负边权的时候,我们就能够通过维护一个队列的二段性,来实现一个简易地dijkstra算法。

于是我们就把这种方式叫做双端队列广搜

二、例题

1、问题

在这里插入图片描述

2、分析

这个我们就可以把翻转电线的次数看作边权,如果不翻转的话,就是0,如果翻转的话就是1。

现在让求的是最小的翻转次数,即从(0,0)右下角的最短路径。

由于只存在两个非负边权,因此我们可以使用双端队列广搜算法

这道题在知道该算法后,还有一个难点就是如何建图。

在这里插入图片描述

我们的BFS是在红色图中进行的,因此我们先看看红色图中的某个点可以向哪几个方向BFS。

在这里插入图片描述

除了记录它能向哪个方向拓展外,我们还需要记录一下,它是沿着怎样放置的一根电线到达的。

在这里插入图片描述
给图中的四个点标号。

图中的橙色线就是我们通过中心点,到达标号点所需要经过的电线。

我们如果按照标号存下来的话,字符串就是“\ / \ /”

但是“\”是特殊字符,我们需要再输入一个反斜杠即,“\\ / \\ /”

那么这个橙色线是理论上,电线的放置形状。

我们还需要通过中心点,找到该点实际上的电线放置情况。

如果二者相同,则说明不用翻转,边权是0,反之是1。

现在要解决的问题,就是如何通过中心点找到对应位置的实际电线放置情况。

我们刚才的橙色坐标图上,是将电线的坐标写在了电线的重心处。

现在我们将电线的坐标移动到电线所在格子的左上角。

在这里插入图片描述

这样这个图就和我们的红色坐标图统一了。

接着我们就可以计算一下,如何通过中心点,通过偏移,找到真实电线的位置。
在这里插入图片描述

知道了这些后,我们就可以写代码了。

三、代码

#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int, int > pii;
const int N = 510, M = N * N;
const int INF = 0x3f3f3f3f;
int n, m;
char g[N][N];
bool st[N][N];
int dis[N][N];int bfs()
{memset(dis, 0x3f, sizeof dis);memset(st, 0, sizeof st);deque<pii>q;int dx[4] = {-1, -1, 1, 1}, dy[4] = {-1, 1, 1, -1};int ix[4] = {-1, -1, 0, 0}, iy[4] = {-1, 0, 0, -1};char cs[] = "\\/\\/";q.push_front({0, 0});dis[0][0] = 0;while(q.size()){pii t = q.front();q.pop_front();if(st[t.x][t.y])continue;st[t.x][t.y] = true;for(int i = 0; i < 4; i ++ ){int nx = t.x + dx[i];int ny = t.y + dy[i];if(nx >= 0 && nx <= n && ny >= 0 && ny <= m){int d = dis[t.x][t.y] + (g[t.x + ix[i]][t.y + iy[i]] != cs[i]);if(d < dis[nx][ny]){dis[nx][ny] = d;if(g[t.x + ix[i]][t.y + iy[i]] != cs[i]){q.push_back({nx, ny});}else{q.push_front({nx, ny});}}}}}return dis[n][m];
}void solve()
{cin >> n >> m;for(int i = 0; i < n; i ++ )cin >> g[i];int t = bfs();if(t == INF)cout << "NO SOLUTION\n";else cout << t << "\n";}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;cin >> t;while(t -- ){solve();}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_255782.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows/VM虚拟机安装黑群晖6.1-----保证有效而且简单操作

1视频&#xff1a;Windows/VM虚拟机安装黑群晖教程_哔哩哔哩_bilibili2:网址&#xff1a;Synology Web Assistant3&#xff1a;重新打开群晖操作步骤1&#xff1a;按着视频下载好资源后&#xff0c;按照视频操作&#xff0c;途中修改地方&#xff08;两个情况选择其中一个&…

Flowable进阶学习(九)数据对象DataObject、租户Tenant、接收任务ReceiveTask

文章目录一、数据对象DataObject二、租户 Tenant三、接收任务 ReceiveTask案例一、数据对象DataObject DataObject可以⽤来定义⼀些流程的全局属性。 绘制流程图&#xff0c;并配置数据对象&#xff08;不需要选择任意节点&#xff09; 2. 编码与测试 /*** 部署流程*/ Test…

函数/任意波形发生器 DG5072 技术资料

函数/任意波形发生器 DG5072 DG5000人性化的界面设计和键盘布局&#xff0c;给用户带来非凡体验&#xff1b;丰富的标准配置接口&#xff0c;可轻松实现仪器远程控制&#xff0c;为用户提供更多解决方案。 产品特性 4.3英寸16M真彩TFT液晶显示屏 350 MHz、250MHz、100 MHz或70…

微信卸载后重装的聊天记录还能找回吗?

很多人微信卸载后&#xff0c;问能不能恢复之前的聊天记录&#xff1f; 我想大家肯定都去百度搜索了&#xff0c;能搜出来可行的办法了么&#xff0c;没有是吧&#xff0c;那就看看我能不能帮到你&#xff0c;根据我的经验来解决。 答&#xff1a;理论上是不能的&#xff0c;因…

详细聊聊spring核心思想

犹记我当年初学 Spring 时&#xff0c;还需写一个个 XML 文件&#xff0c;当时心里不知所以然&#xff0c;跟着网上的步骤一个一个配置下来&#xff0c;配错一个看着 error 懵半天&#xff0c;不知所谓地瞎改到最后能跑就行&#xff0c;暗自感叹 tmd 这玩意真复杂。 到后来用上…

C语言入门教程||C语言 循环||C语言 函数

C语言 循环有的时候&#xff0c;可能需要多次执行同一块代码。一般情况下&#xff0c;语句是顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。编程语言提供了允许更为复杂的执行路径的多种控制结构。循环语句允许我们多次执…

【Django】云笔记项目

一、介绍 用户可在系统中记录自己的笔记&#xff0c;用户的数据被存储在云笔记平台&#xff1b;用户和用户之间的数据为隔离存储&#xff08;登陆后才能使用相关笔记功能&#xff0c;且只能查阅自己的笔记&#xff09; 二、功能拆解 1、用户模块 注册&#xff1a;成为平台…

【Java 面试合集】简述下自定义异常的应用场景

简述下自定义异常的应用场景 1. 概述 如上图所示&#xff0c;我们想回答这个问题就要了解异常的基本结构。哪些是我们可以控制的&#xff0c;哪些是我们不能控制的。 也许有人会问了&#xff0c;其实在逻辑中可以多加判断&#xff0c;为什么要需要自定义呢。 其实判断的内容无…

跳跃游戏 II 解析

题目描述给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处:0 < j < nums[i] i j < n返回到达 nums[n - 1] 的…

【i2c协议介绍】

文章目录协议简单介绍五种速度模式master/slave和transmitter/receiver关系第一种情况&#xff1a;master作为transmitter&#xff0c;slave作为receiver第二种情况&#xff1a;当master作为receiver&#xff0c;slave作为transmitteri2c基本信号start产生stop信号数据传输有效…

基于OpenCV 的车牌识别

基于OpenCV 的车牌识别 车牌识别是一种图像处理技术&#xff0c;用于识别不同车辆。这项技术被广泛用于各种安全检测中。现在让我一起基于 OpenCV 编写 Python 代码来完成这一任务。 车牌识别的相关步骤 1. 车牌检测&#xff1a;第一步是从汽车上检测车牌所在位置。我们将使用…

《Spring揭秘》记录

IOC部分 IOC不等于IOC容器&#xff0c;即使不使用spring&#xff0c;我们也可以使用IOC&#xff0c;只不过spring提供了IOC容器实现。Spring的IoC容器的功能就包含一个提供依赖注入服务的IoC Service Provider。它提供两方面的支持&#xff0c;业务对象的构建管理和业务对象间的…

python读取.stl文件

目录 .1 文本方式读取 1.2 stl解析 1.3 stl创建 .2 把点转换为.stl .1 文本方式读取 代码如下 stl_path/home/pxing/codes/point_improve/data/003_cracker_box/0.stlpoints[] f open(stl_path) lines f.readlines() prefixvertex num3 for line in lines:#print (l…

《里奥哈酒友记》 | 里奥哈的历史—品鉴瑞格尔侯爵葡萄酒

2022年末&#xff0c;里奥哈大使组合怪怪和思羽完成了里奥哈线上活动两大“壮举”&#xff0c;10期《里奥哈酒友记》系列视频和40集《美酒之乡——里奥哈》有声专辑&#xff0c;吸引了许多葡萄酒资深爱好者的目光&#xff0c;也成功地让更多的人了解到里奥哈。由里奥哈推广大使…

windows无法访问指定设备路径或文件怎么办?2个解决方案

有时候Win10电脑打不开程序或文件&#xff0c;windows无法访问指定设备路径或文件该怎么办&#xff1f;原因是什么呢&#xff1f;一般导致这种情况的出现&#xff0c;大多是因为我们的电脑缺乏相应的查看权限&#xff0c;我们只需要通过赋予权限就可以解决这个难题了。 操作环境…

【Java】TCP的三次握手和四次挥手

三次握手 TCP三次握手是一个经典的面试题&#xff0c;它指的是TCP在传递数据之前需要进行三次交互才能正式建立连接&#xff0c;并进行数据传递。&#xff08;客户端主动发起的&#xff09;TCP之所以需要三次握手是因为TCP双方都是全双工的。 什么是全双工&#xff1f; TCP任何…

手把手教你将Eureka升级Nacos注册中心

由于原有SpringCloud体系版本比较老&#xff0c;最初的注册中心使用的Eureka后期官方无升级方案&#xff0c;配置中心无法在线管理配置&#xff0c;还有实时上下线的问题&#xff0c;因此需要将原有系统的Eureka服务升级Nacos注册心服务。原有版本SpringBoot1.5.15、SpringClou…

C#【必备技能篇】Winform跨线程更新进度条的实例

文章目录实例一&#xff1a;【方便理解&#xff0c;常用&#xff01;】源码&#xff1a;运行效果&#xff1a;实例二&#xff1a;【重在理解代码本身】源码&#xff1a;运行效果&#xff1a;参考&#xff1a;实例一&#xff1a;【方便理解&#xff0c;常用&#xff01;】 跨线…

独立图片服务器有什么突出之处

服务器是网络中非常重要的设施&#xff0c;承载着不同流量的访问&#xff0c;这就要求服务器具有快速的吞吐量、高稳定性和高可靠性。独立图片服务器作为独立服务器的衍生品&#xff0c;在数据利用方面的应用可以为企业在数据处理和分析方面带来一场革命。本文就将介绍独立图片…

Cadence OrCAD 16.6 原理图导出带标签pdf(免费软件版)

Cadence OrCAD 16.6原理图导出带标签pdf&#xff08;免费软件版&#xff09; Cadence OrCAD 16.6 导出有标签的原理图&#xff0c;页面导航、跨页符、元件封装等&#xff0c;更方便阅读。找了一些可用的免费软件。 安装软件 系统win10 22H2&#xff0c;OrCAD SPB 16.6 根据…