搜索-BFS

发布于:2025-03-31 ⋅ 阅读:(25) ⋅ 点赞:(0)

马上蓝桥杯了,最近刷了广搜,感觉挺有意思的,广搜题类型都差不多,模板也一样,大家写的时候可以直接套模板

这里给大家讲一个比较经典的广搜题-迷宫

题目问问能否走到 (n,m) 位置,假设最后一个点是我们的(n,m) 点

那我们如何判断是否可以走到我们的(n,m)点呢?

题目给我们的起点是(1,1),然后对应的数组下标就是(0,0),(下面我们说的坐标都是我们的数组下标)首先我们定义我们的一个二维数组maze来存储我们的迷宫,然后现在从(0,0)坐标开始,我们需要定义一个队列来存储我们的可用的坐标,遍历我们的坐标,然后这里我们有四个方向可以走,上下左右,就是说当我们达到该坐标的时候,需要遍历上下左右四个方向,然后将可以用的坐标进行存储到我们的队列当中

但是通过上图可以看到,当向上和向左的时候,我们的坐标越界了,没有意义,所以我们不需要处理这两个坐标,然后向右,我们发现是面墙,因为题目说" # "是一个墙,这个坐标是不能使用的,所以这里我们遍历到该坐标的时候需要一个判断看该坐标是不是" . " ,然后遍历下面,发现既没有越界,也不是墙,所以我们就将该坐标(1,0)添加到我们的队列里面,然后(0,0)坐标使用过了,我们就使用pop()方法将它删除,因为我们遍历所有可添加的坐标,使用需要将不用的坐标进行删除

通过第一次(0,0)坐标的四个方向遍历,我们已经(1,0)坐标添加上去,然后继续进行遍历~

遍历完成之后添加我们的(2,0),但是当我们遍历上面的点时,我们发现有问题,因为我们已经走过(0,0)点了,使用我们还需要一个数组dist,来储存我们走过的坐标....,如果走过,就让该坐标当下的值变成1,0表示没有走过,1表示走过,如果没有走过我们才将坐标添加上去,依次类推,直到找到我们的(n,m)点,然后进行输出,如果遍历完还没有找到,就输出No

定义:

 char maze[N][N];//迷宫
 int dist[N][N];//路径
 queue<pair<int,int> > q;//定义队列

初始化:

  memset(dist,0,sizeof(dist));
  dist[0][0]=1;//1表示走过,0表示没有走过
  q.push({0,0});//初始化队列

定义上下左右移动数组:
 

   int dx[4]={-1,1,0,0};
   int dy[4]={0,0,-1,1};

遍历队列坐标:(广搜模板)

    while(!q.empty()){
        auto[x,y]=q.front();
        q.pop();
        // 遍历上下左右四个方向
        for(int i=0;i<4;i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            //判断是否到达了该坐标
            if(nx==n-1&&ny==m-1){
                cout<<"Yes";
                return 0;
            }
            //判断是否可以添加该坐标
            if(nx>=0&&nx<=n&&ny>=0&&ny<=m&&maze[nx][ny]=='.'&&dist[nx][ny]==0){
                dist[nx][ny]=1;
                q.push({nx,ny});
            }
        }
    }

 

下面是代码实现:

#include<bits/stdc++.h>
using namespace std;
const int N=100;
char maze[N][N];//迷宫
int dist[N][N];//路径
queue<pair<int,int> > q;
int main(){
    int n,m;
    cin>>n>>m;
    dist[0][0]=1;//1表示走过,0表示没有走过
    q.push({0,0});//初始化队列
    memset(dist,0,sizeof(dist));
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>maze[i][j];
        }
    }
    //定义上下左右移动数组
    int dx[4]={-1,1,0,0};
    int dy[4]={0,0,-1,1};
    while(!q.empty()){
        auto[x,y]=q.front();
        q.pop();
        // 遍历上下左右四个方向
        for(int i=0;i<4;i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(nx==n-1&&ny==m-1){
                cout<<"Yes";
                return 0;
            }
            if(nx>=0&&nx<=n&&ny>=0&&ny<=m&&maze[nx][ny]=='.'&&dist[nx][ny]==0){
                dist[nx][ny]=1;
                q.push({nx,ny});
            }
        }
    }
    cout<<"No";
    return 0;
}

如果大家听懂了,可以写一下P1443 马的遍历 - 洛谷  题来检测一下,一样的类型