UVa The Morning after Halloween 万圣节后的早晨 双向BFS
题目链接:The Morning after Halloween
题目描述:
给定一个二维矩阵,图中有障碍物和字母,你需要把小写字母移动到对应的大写字母位置,不同的小写字母可以同时移动(上下左右四个方向或者保持不动 ),但是移动之后两个字母不能重合,同时移动后不能是两个字母发生了位置的交换。
上图给出了一种情况即该情况下的四种合法移动。
同时题目保证任意一个2×22\times22×2的子区域中一定至少含有一个障碍物,同时边界一定是障碍物。
题解:
我们可以把每个矩阵的看成一个状态进行BFSBFSBFS但是这样状态的个数比较多。
由于题目保证了很小的区域有障碍这也就变相说明了题目可以到达的点并不会很多,所以我们可以把每个可以经过的点进行编号,然后记录字母落在点的编号的三元组(缺少的字母用000来表示,这意味着点的编号需要从111开始),然后将三元组看成是状态,而每一次移动看成是一条边,这样我们只需要进行BFSBFSBFS即可找到目标状态的最少移动次数(在移动的时候,我们需要判断是否违反规则,例如移动后两个字母在同一个位置,或者移动导致两个相邻的字母发生的交换)。由于本题的目标状态也是已知的,那么我们可以使用双向BFSBFSBFS也就是从目标状态和初始状态同时进行BFSBFSBFS当在中间的某个状态相遇的时候,就意味着找到了最少花费,在代码中我们只需要两个队列就可以实现双向BFSBFSBFS一个放入初始状态进行搜索,一个放入目标状态进行搜索。
为什么需要双向BFSBFSBFS?双向BFSBFSBFS通常情况下能够让时间复杂度下降。原理实际上是因为每一次都选择含有较少的节点进行扩展,这样能一定程度上节省时间。
双向BFSBFSBFS的代码应该是每次选择较小的队列进行扩展,而不是轮流进行扩展(如果是轮流进行扩展那么实际上和单向BFSBFSBFS没有太大的差别)。
代码:
#include <bits/stdc++.h>const int DIRECTION_NUM = 5;
const int MAXH = 16 + 1;
const int MAXW = 16 + 1;
const int MAX_NODE = MAXH * MAXW;using namespace std;int w, h, n, nodeNum;
char g[MAXH][MAXW];
int dx[] = {0, 1, -1, 0, 0};
int dy[] = {0, 0, 0, 1, -1};
vector<int> es[MAX_NODE];
int nodeId[MAXH][MAXW];
map<char, int> s, t;
int dis[MAX_NODE][MAX_NODE][MAX_NODE];
int inQ[MAX_NODE][MAX_NODE][MAX_NODE];struct State
{int a, b, c; //最多三个字母位置的结点编号State() {}State(int a, int b, int c) : a(a), b(b), c(c) {}State& operator=(map<char, int> &rhs){a = b = c = 0;auto iter = rhs.begin();for (size_t i = 0; i < n; i++) {if (i == 0) { a = iter->second; }else if (i == 1) { b = iter->second; }else if (i == 2) { c = iter->second; }iter++;}return *this;}
}st, ed;void buildGraph()
{nodeNum = 1;s.clear();t.clear();for (int i = 0; i < MAX_NODE; i++) { es[i].resize(0); }for (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {if (g[i][j] == '#') { continue; }nodeId[i][j] = nodeNum++;if (islower(g[i][j])) {s[g[i][j]] = nodeId[i][j];} else if (isupper(g[i][j])) {t[g[i][j]] = nodeId[i][j];}}}st = s;ed = t;es[0].push_back(0);for (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {if (g[i][j] == '#') { continue; }for (int k = 0; k < DIRECTION_NUM; k++) {int nx = i + dx[k];int ny = j + dy[k];if (g[nx][ny] == '#') { continue; }es[nodeId[i][j]].push_back(nodeId[nx][ny]);}}}
}bool conflict(int newA, int newB, int a, int b) { return (newA == newB && newA != 0) || (newA == b && newB == a && newA != 0 && newB != 0); }int bfs(queue<State> &q, int nowQ)
{int size = q.size();int a, b, c;while(size--) {State now = q.front();q.pop();a = now.a, b = now.b, c = now.c;for (auto newA : es[a]) {for (auto newB : es[b]) {if (conflict(newA, newB, a, b)) { continue; }for (auto newC : es[c]) {if (conflict(newA, newC, a, c) || conflict(newB, newC, b, c)) { continue; }if (inQ[newA][newB][newC] == nowQ) { continue; }if (inQ[newA][newB][newC] == 3 - nowQ) { // 在另一个队列中cout << dis[newA][newB][newC] + dis[a][b][c] + 1 << endl;return 0;}dis[newA][newB][newC] = dis[a][b][c] + 1;inQ[newA][newB][newC] = nowQ;q.push({newA, newB, newC});}}}}return -1;
}void dBfs()
{queue<State> qs;queue<State> qt;memset(inQ, 0, sizeof(inQ));qs.push(st);qt.push(ed);dis[st.a][st.b][st.c] = 0;inQ[st.a][st.b][st.c] = 1;dis[ed.a][ed.b][ed.c] = 0;inQ[ed.a][ed.b][ed.c] = 2;while (!qs.empty() && !qt.empty()) {if (qs.size() < qt.size()) { // 优先选择队列短的队列进行bfsif(bfs(qs, 1) != -1) { return; }}else {if(bfs(qt, 2) != -1) { return; };}}
}int main()
{ios::sync_with_stdio(false);while(cin >> w >> h >> n) {if (w == 0 && h == 0 && n == 0) { break; }cin.get(); //读取末尾的换行for (int i = 0; i < h; i++) { cin.getline(g[i], MAXW); } // cin.getline读取的数据末尾没有'\n', cin.getline会保证末尾有结束符0,所以最多读取MAXW-1个有效字符buildGraph();dBfs();}return 0;
}
相关文章:
UVa The Morning after Halloween 万圣节后的早晨 双向BFS
题目链接:The Morning after Halloween 题目描述: 给定一个二维矩阵,图中有障碍物和字母,你需要把小写字母移动到对应的大写字母位置,不同的小写字母可以同时移动(上下左右四个方向或者保持不动 ࿰…...
Connext DDS属性配置参考大全(3)
Transport传输dds.participant.logging.time_based_logging.process_received_messagedds.participant.logging.time_based_logging.process_received_message.timeout...
Docker-安装Jenkins-使用jenkins发版Java项目
文章目录0.前言环境背景1.操作流程1.1前期准备工作1.1.1环境变量的配置1.2使用流水线的方式进行发版1.2.1新建流水线任务1.2.2流水线操作工具tools步骤stages步骤1:拉取代码编译步骤2:发送文件并启动0.前言 学海无涯,旅“途”漫漫,“途”中小记ÿ…...
spring 中的 Bean 是否线程安全
文章目录结论1、spring中的Bean从哪里来?2、spring中什么样的Bean存在线程安全问题?3、如何处理spring Bean的线程安全问题?结论 其实,Spring 中的 Bean 是否线程安全,其实跟 Spring 容器本身无关。Spring框架中没有提…...
微电网两阶段鲁棒优化经济调度方法[3]【升级优化版本】(Matlab代码实现)
💥💥💥💞💞💞欢迎来到本博客❤️❤️❤️💥💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑…...
C++入门教程||C++ 数据类型||C++ 变量类型
C 数据类型 使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。 您可能需要存储各种数据类型(比如字符型、宽字符型、整型…...
【visio使用技巧】图片导出pdf时去掉多余空白
问题 在visio导出pdf格式的图片时,往往会存在多余的白边,如下图所示: 解决方法 依次点击:菜单栏→文件→选项→自定义功能区→勾选“开发工具”→确定。 依次点击菜单栏→开发工具→显示ShapeSheet→页→Print Properties→将…...
Rust语言之Option枚举类型
概述 Option是Rust语言设计中最重要的枚举类型之一,它编码了其它语言中空值与非空值的概念,差异在于,Rust不会允许你像其它语言一样以非空值的方式来使用一个空值,这避免了很多错误。Option在标准库中的定义如下: pu…...
基于TimeQuest时序优化原理和方法
💡 回顾基于RTL逻辑时序优化的基本思路,在关键路径中插入寄存器来优化时序 分析最坏路径 通过前面对TimeQuest软件的理解,基本上可以找到关键路径,此文章主要对关键路径时序进行优化,使设计达到时序要求,以…...
LeetCode第332场周赛
2023.2.12LeetCode第332场周赛 6354. 找出数组的串联值 思路 双指针模拟,两个指针相遇的时候要特判 算法 class Solution { public:long long findTheArrayConcVal(vector<int>& nums) {long long ans 0;int i 0, j nums.size() - 1;while (i <…...
2023-2-12刷题情况
字母板上的路径 题目描述 我们从一块字母板上的位置 (0, 0) 出发,该坐标对应的字符为 board[0][0]。 在本题里,字母板为board [“abcde”, “fghij”, “klmno”, “pqrst”, “uvwxy”, “z”],如下所示。 我们可以按下面的指令规则行动…...
拉普拉斯矩阵
拉普拉斯算子 Δff(xi1,yj)f(xi−1,yj)f(xi,yj1)f(xi,yj−1)−4f(xi,yj)∑(k,l)∈N(i,j)(f(xk,yl)−f(xi,yj))\begin{aligned} \Delta f & f\left(x_{i1}, y_j\right) f\left(x_{i-1},y_j\right) f\left(x_i,y_{j1}\right)f\left(x_i,y_{j-1}\right) - 4f\left(x_i,y_j\r…...
Top-1错误率、Top-5错误率等常见的模型算法评估指标解析
Top-1 错误率:指预测输出的概率最高的类别与人工标注的类别相符的准确率,就是你预测的label取最后概率向量里面最大的那一个作为预测结果,如过你的预测结果中概率最大的那个分类正确,则预测正确,否则预测错误。比如预测…...
Urho3D 容器类型
Urho3D实现了自己的字符串类型和模板容器,而不是使用STL。其基本原理如下: 在某些情况下提高了性能,例如使用PODVector类时。保证字符串和容器的二进制大小,以允许例如嵌入Variant对象内。减少了编译时间。直接命名和实现&#x…...
C语言学习笔记(四): 循环结构程序设计
while语句 定义 While语句是C语言中的循环语句,它按条件循环执行语句,直到条件不满足为止 语法格式如下: while(condition) {//循环体内容; }使用实例 求123…100 include <stdio.h> int main(){int i 1, sum 0;while (i<100){sum i …...
02 OpenCV图像通道处理
1 通道提取与合并 在数字图像处理中,图像通道是指一个图像中的颜色信息被分离为不同的颜色分量。常见的图像通道包括RGB通道、灰度通道、HSV通道等。 RGB通道是指将图像分离为红色、绿色和蓝色三个颜色通道,每个通道表示相应颜色的亮度。这种方式是最常…...
微信小程序图书馆座位预约管理系统
开发工具:IDEA、微信小程序服务器:Tomcat9.0, jdk1.8项目构建:maven数据库:mysql5.7前端技术:vue、uniapp服务端技术:springbootmybatis本系统分微信小程序和管理后台两部分,项目采用…...
有限元分析学习一
系列文章目录 有限元分析学习一 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录前言一、有限元方法的简单介绍1.1 有限元的基础概念1.2 有限元软件发展历史1.3 有限元软件二、弹性力学的简单介绍2.1.…...
android avb2.0 总结
1、android vbmeta结构深入解析 2、android libavb深入解读 看完结构与代码,进一步了解了avb 比如vbmeta的结构、5种描述符、hash公钥签名存储位置 多层vbmeta结构、无vbmeta分区的验证逻辑、hash计算对比、公钥验证、签名验签、5种描述符体的处理 但是还有一些问题没有解决 如…...
聊天机器人-意图识别类,开源库推荐
随着人工智能和自然语言处理技术的不断发展,聊天机器人在商业、教育、医疗等领域的应用越来越广泛。因此,开源聊天机器人代码库也逐渐成为了热门话题。 开源聊天机器人代码库可以帮助开发者快速构建功能强大的聊天机器人,而不必从头开始编写…...
Java 标识符以及修饰符
Java 标识符Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。关于 Java 标识符,有以下几点需要注意:所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_&…...
封装、继承、Super、重写、多态instanceof类型转换的使用以及个人见解
这里写目录标题封装继承supersuper和this的区别重写多态instanceof类型转换封装 之前我们调用共有的属性,是直接可以调用的 但是属性私有后,无法在直接.调用 只能通过getset调用 继承 super 可以直接调用父类中属性和方法,私有的无法做 其…...
day13_面向对象的三大特征之一(封装)
封装概述 为什么需要封装? 现实生活中,每一个个体与个体之间是有边界的,每一个团体与团体之间是有边界的,而同一个个体、团体内部的信息是互通的,只是对外有所隐瞒。例如:我们使用的电脑,内部…...
越界访问数组
越界访问是指访问(操作修改)了不属于自己的空间 我们以如下代码为例:此代码在vs中进行 #include <stdio.h> int main() {int i 0;int arr[] {1,2,3,4,5,6,7,8,9,10};for(i0; i<12; i){arr[i] 0;printf("hello\n");}r…...
软件设计(十)--计算机系统知识
软件设计(九)https://blog.csdn.net/ke1ying/article/details/128990035 一、效验码 奇偶效验:是一种最简单的效验方法。基本思想是:通过在编码中增加一个效验位来使编码中1的个数为奇数(奇效验)或者为偶…...
【不知道是啥】浅保存哈
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...
2021 WAIC 世界人工智能大会参会总结
前言 2021 年世界人工智能大会(WAIC)于2021年7月7日至10日在上海世博展览馆举办,本届大会继续秉持「智联世界」的理念,以「众智成城」为主题,促进全球人工智能创新思想、技术、应用、人才和资本的集聚和交流ÿ…...
ThingsBoard-实现定时任务调度器批量RPC
1、概述 ThingsBoard-CE版是不支持调度器的,只有PE版才支持,但是系统中很多时候需要使用调度器来实现功能,例如:定时给设备下发rpc查询数据,我们如何来实现呢?下面我将教你使用巧妙的方法来实现。 2、使用什么实现 我们可以使用规则链提供的一个节点来实现,这个节点可…...
MySQL数据库调优————数据库调优维度及测试数据准备
MySQL性能优化金字塔法则 不合理的需求,会造成很多问题。(比如未分页,数据需要多表联查等)做架构设计的时候,应充分考虑业务的实际情况,考虑好数据库的各种选择(比如是否要读写分离,…...
电子货架标签多种固定方式
2.1寸和2.9寸电子价格标签多种固定方式: 1、桌面支架,放置在桌面或是货架上,用于桌面产品的价格或是信息显示 2、粘贴架,方便用于墙面桌面等应用 3、半透明支架,用于货架上的商品吊挂显示价格信息 4、轨道架ÿ…...
propulsion wordpress/seo网站排名优化软件
Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 借用网友的一张图,刚开始看code的时候,存在了误区,以为系统分配了n个buffer_size的buffer,后来才发现图里这么多buffer_size在code中其实都只是模拟一个循环buffer,读写指针的数值一直增…...
鄱阳有做百度网站的/阿里云搜索引擎
关于实现自定义滚轮,首先要对整个布局进行了解:1、 1.需要显示的层级 和 2.需要被滚动层级 的关系: 1--层级1具有 溢出隐藏 属性,目的是为了隐藏 层级2 多出的部分。 2--由于在层级1的包裹之下层级2溢出隐藏部分可以通过控…...
金华网站建设明细报价表/新网站友链
http://www.cnjm.net/tech/article2049.html 本文版权归原作者,中国JAVA手机网收录本文的目的是让更多人阅读到此文章。转载请注明出处为中国JAVA手机网<www.cnjm.net> 来自:http://www.cnjm.net/tech/article2049.html 由于无线设备所能支持的网络协议非常有…...
长沙做网站seo优化外包/如何在百度发布广告
:%!python -m json.tool https://www.jianshu.com/p/91c2d7a54eb7...
诸城做网站收费/友情链接的网站有哪些
经过这几天的工作,让我进一步的了解到CSS3的强大,原本许多需要js才能实现的动画效果,现在通过CSS3就能轻易实现了,但是CSS3也有自身的不足,例如说在动画出发触发上就没有js灵活,因此我就开始考虑将CSS3与Js…...
公司简介模板免费图片/seo研究中心
一、精密空调的结构及工作原理 精密空调主要由压缩机、冷凝器、膨胀阀和蒸发器组成。一般来说空调机的制冷过程为:压缩机将经过蒸发器后吸收了热能的制冷剂气体压缩成高压气体,然后送到室外机的冷凝器;冷凝器将高温高压气体的热能通过风扇向周围空气中释…...