宽度优先搜索解决迷宫问题(最小步数求解)

本文详细介绍了宽度优先搜索(BFS)在寻找迷宫中从起点到终点的最小步数问题中的应用,包括基本原理、步骤、优势以及代码实现,同时提到了注意事项和特殊情况处理。

1.宽度优先搜索解决迷宫最小步数问题

在迷宫问题中,除了找到从起点到终点的路径外,有时我们还关心如何以最小的步数到达终点。宽度优先搜索(BFS)是一种非常适合解决这类问题的算法。BFS从起点开始,逐层向外扩展搜索,直到找到终点。由于它首先探索离起点最近的节点,因此找到的路径通常是步数最少的。

2.宽度优先搜索的基本原理

宽度优先搜索是一种用于遍历或搜索树或图的算法。在迷宫问题中,我们可以将迷宫看作一个图,其中每个单元格都是一个节点,可通行的单元格之间用边相连。BFS使用队列数据结构来保存待探索的节点,并按照它们离起点的距离逐层探索。

3.BFS解决迷宫最小步数问题的步骤

  1. 初始化

    • 创建一个迷宫地图,表示每个单元格是否可以通行。
    • 设置起点和终点。
    • 创建一个队列用于保存待探索的节点。
    • 创建一个与迷宫大小相同的距离数组,用于记录从起点到每个单元格的最短距离。初始时,所有单元格的距离都设为无穷大(或一个很大的数),起点的距离设为0。
  2. 开始搜索

    • 将起点加入队列。
    • 标记起点为已访问。
  3. 广度搜索

    • 从队列中取出一个节点。
    • 检查该节点是否为终点。如果是,则结束搜索,此时的步数即为从起点到终点的最小步数。
    • 如果不是终点,则遍历该节点的所有邻居节点(即可以通行的单元格)。
      • 对于每个未访问过的邻居节点,执行以下操作:
        • 更新其距离值为当前节点距离值加1。
        • 将其加入队列。
        • 标记为已访问。
      • 如果邻居节点已经被访问过,并且其距离值不小于当前计算出的距离值,则忽略该节点,避免重复计算。
  4. 输出结果

    • 如果找到终点,则可以输出从起点到终点的最小步数,以及可能的路径。
    • 如果没有找到终点,则说明起点和终点不可达。

4.BFS解决迷宫最小步数问题的优势

  • BFS能够保证找到的路径是最短的,因为它首先探索离起点最近的节点。
  • 相比于深度优先搜索,BFS在解决迷宫最小步数问题时通常更加高效,因为它避免了不必要的深入搜索。

5.注意事项

  • BFS的空间复杂度较高,因为它需要存储待探索的节点和已访问的节点信息。对于大型迷宫,可能会导致内存消耗较大。
  • 在实现BFS时,要注意避免重复访问已经探索过的节点,以免造成不必要的计算。

6.代码实现

#include<iostream>

using namespace std;

int t[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//右下左上向量
struct node
{
    int x;
    int y;
    //int f;//父编号
    int s;//step
};

int main(){
    struct node que[2501];
    int a[51][51]={0},book[51][51]={0};
    int head,tail;
    int i,j,k,m,n,startx,starty,p,q,tx,ty,flag;

    cin>>n>>m;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)//起始条件=1,终止条件<=
            cin>>a[i][j];
            
    cin>>startx>>starty>>p>>q;
    //队列初始化
    head=tail=1;
    que[tail].x=startx;
    que[tail].y=starty;
    //que[tail].f=0;
    que[tail].s=0;
    tail++;
    book[startx][starty]=1;

    flag=0;

    while (head<tail)
    {
        for(k=0;k<=3;k++){
            tx=que[head].x+t[k][0];
            ty=que[head].y+t[k][1];
            if (tx<1||tx>n||ty<1||ty>m)continue;//检查越界
            if (a[tx][ty]==0&&book[tx][ty]==0)//未走过且非障碍
            {
                book[tx][ty]=1;
                que[tail].x=tx;
                que[tail].y=ty;
                //que[tail].f=que[head].f+1;
                que[tail].s=que[head].s+1;
                tail++;
            }
            if (tx==p&&ty==q)
            {
                flag=1;
                break;
            }
            
        }
        if (flag==1)break;
        head++;
    }
    cout<<"step="<<que[tail-1].s;
    return 0;

}
/* 5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3 */

 另一种写法

#include<iostream>
#define MAX 101
using namespace std;

int t[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//右下左上向量
struct node
{
    int x;
    int y;
    int s;//step
}que[MAX*MAX];
int main(){
int n,m,sx,sy,ex,ey,map[MAX][MAX],book[MAX][MAX];
cin >> n >> m;
for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        cin>>map[i][j];
cin>> sx >> sy;
cin>> ex >> ey;
//chushihua
int head=1,tail=1;
que[1].x=sx;
que[1].y=sy;
que[1].s=0;
book[sx][sy]=1;
tail++;
int flag=0;
while(head<tail){
    
    for (int i = 0; i < 4; i++)
    {
        que[tail].x=que[head].x+t[i][0];
        que[tail].y=que[head].y+t[i][1];
        que[tail].s=que[head].s+1;
        if (que[tail].x==ex&&que[tail].y==ey)
        {
            flag=1;
            break;
        }
        if(que[tail].x<1||que[tail].y<1||que[tail].x>m||que[tail].y>n||map[que[tail].x][que[tail].y]==1||book[que[tail].x][que[tail].y]==1)continue;
        book[que[tail].x][que[tail].y]=1;
        tail++;
    }
    if (flag)break;
    head++;
    
}
    if (flag)cout<<que[tail].s<<endl;
    else cout<<"no";
    return 0;
}

 7.补充

如果起点和终点重合,以上方法算出来最小步数为2。如果没有确保起点和终点不能重合,可以单独用if判断一下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值