问题描述:捉迷藏的规则与挑战
mzc家非常富裕,有n个男家丁,他们打算一起玩捉迷藏。现在mzc要来寻找他的男家丁,这是一项不小的挑战。首先,他们的藏身之处是一个n行m列的空间,其中,mzc用m表示,男家丁用d表示,不能走的地方用#表示,空地用.表示。成败关键在于,mzc需要找到男家丁的最短移动次数。如果找到了,返回对应的移动次数;如果找不到,就输出"No Way!"。
原题链接:Mzc和男家丁的游戏 - 洛谷
我们将全面解析一段使用C++实现的寻路算法代码。代码通过一种广度优先搜索(BFS)的方式,在一个字符矩阵中寻找从起点(标记为'm')到终点(标记为'd')的最短路径。沿途中会遇到一些障碍(标记为'#'),我们需要规避这些阻碍来找寻通向目的地的最短路线。
代码的重点在于BFS算法的实现,通过一种特殊的队列处理顺序,它能够确保总是首先探索距离起点最近的位置。
#include<iostream>
#include<cstring>
using namespace std;
typedef pair<int,int> PII;
const int N=2e3+10;
PII q[N*N];
char g[N][N];
int dis[N][N];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
int n,m;
首先,我们引入了需要的库并定义了必要的常量和变量。包括一个二维字符数组g
来存储地图,一个距离矩阵dis
来记录每个位置距离起点的步数,还有两个数组dx
和dy
,它们定义了可能的四个移动方向:上、右、下、左。
int bfs(int x,int y)
{
int hh=0,tt=0;
if(g[x][y]=='d')return 0;
memset(dis,-1,sizeof(dis));
q[0]={x,y};
dis[x][y]=0;
while (hh<=tt) {
auto t = q[hh++];
for (int i = 0; i < 4; i++) {
int a = t.first + dx[i], b = t.second + dy[i];
if(a<0||a>=n||b<0||b>=m||dis[a][b]!=-1||g[a][b]=='#')continue;
q[++tt]={a,b};
dis[a][b] = dis[t.first][t.second] + 1;
if (g[a][b]=='d') return dis[a][b];
}
}
return -1;
}
接着,我们有一个bfs
函数,用于执行广度优先搜索的算法。这个函数从一个给定的位置(x,y)开始,在地图上广泛搜索,并计算出最短的路径长度到达'd'
(目的地)。如果从当前位置无法到达目的地,这个函数将返回-1
。
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%s",g[i]);
bool found = false;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(g[i][j]=='m')
{
int steps = bfs(i,j);
if(steps != -1)
{
printf("%d", steps);
found = true;
break;
}
}
}
if(found) break;
}
if(!found) printf("No Way!");
return 0;
}
最后,我们在main
函数中对地图进行初始化,并从起点位置开始执行BFS搜索。一旦发现一个方法到达目标,程序将打印出所需的步骤并结束。如果在所有可能的起点位置都找不到到达目的地的路径,程序将打印出"No Way!"
通过以上代码,我们可以看到BFS寻路算法如何在地图上找到最短路径。这个实现虽然简单,但也非常有效,希望你能从中获取到它的内在逻辑,并能够在自己的项目中运用。
大家可以练习相似题目:离开中山路 - 洛谷