F.幻形之路
#最短路 #BFS #dijkstra
![![[Pasted image 20250614211629.png]]](/https://i-blog.csdnimg.cn/direct/db999edc79484bd8bb809c0378cd8bc7.png)
![![[Pasted image 20250614211647.png]]](/https://i-blog.csdnimg.cn/direct/d65d33778cfa4a829a47d6dd0eb4601a.png)
思路
从起点走到终点的过程可以简化为:
起点→障碍物→k障碍物→终点 起点\to障碍物 \xrightarrow{k}障碍物\to 终点 起点→障碍物k障碍物→终点
因此,只需要找到围住起点的一圈障碍物以及围住终点的一圈障碍物,随后求出这两圈之间的最短路即可!
找到这两圈障碍物可以采用BFS的方式,如果当前点是'#',那么就可以进行标记并continue;
求最短路可以使用Dijkstra或者继续BFS~
法一:Dijkstra
由于这是一个多起点(一圈障碍物)问题,所以开一个超级源点S0S_{0}S0,将所有的起点SiS_{i}Si与其建边,边权为0:S0→0SiS_{0}\xrightarrow{0}S_{i}S00Si
其次将图上的所有点建边:Si→1S上、下、左、右S_{i}\xrightarrow{1}S_{上、下、左、右}Si1S上、下、左、右
以超级源点S0S_{0}S0为起点跑一遍dj就可以快乐出答案啦!
值得一提的是,如果第一遍对最初的起点(1,1)(1,1)(1,1)BFS的时候已经遍历到了终点(n,m)(n,m)(n,m),那么应当直接输出0。
本人因为这个边界条件卡了快一个小时
法二:BFS
相比于dj,BFS不需要建边,但是更考验染色以及细节的处理
第一遍BFS的用vis数组标记,第二遍BFS用数组vis2标记
在队列deque中塞入所有的障碍物起点SiS_{i}Si,判断是否可以塞入队列的条件是vis数组,判断是否结束的条件是vis2数组:
如果BFS过程中,当前点(x,y)(x,y)(x,y)在vis2上已经被标记了,那么就说明已经找到了从障碍物起点到障碍物终点的最短路!直接输出步数step即可~
代码实现
Dijkstra
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#


2902

被折叠的 条评论
为什么被折叠?



