BFS实现最短路算法(最少移动次数)

问题描述:捉迷藏的规则与挑战

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来记录每个位置距离起点的步数,还有两个数组dxdy,它们定义了可能的四个移动方向:上、右、下、左。

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寻路算法如何在地图上找到最短路径。这个实现虽然简单,但也非常有效,希望你能从中获取到它的内在逻辑,并能够在自己的项目中运用。

大家可以练习相似题目:离开中山路 - 洛谷

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值