迷宫问题(BFS)

给定一个大小为N*M的迷宫,由通道('.')和墙壁('#')组成,其中通道S表示起点,通道G表示终点,每一步移动可以达到上下左右中不是墙壁的位置。试求出起点到终点的最小步数。(本题假定迷宫是有解的)(N,M<=100)

样例输入:
10 10
#S######.#
......#..#
.#.##.##.#
.#........
##.##.####
....#....#
########.#
....#.....
.####.###.
....#...G#

这道题目以及解法均来自《挑战程序设计竞赛(第2版)》第34页-36页;书中解法使用了真正的队列,而我在这里是用了数组模拟队列,但是结果都是一样的。

个人觉得这个例题很好地表现了广度优先搜索是如何与队列先进先出(FIFO)的思想联系起来的,通过不断取得某个状态后能够达到的所有状态并将其加入队列, 并且由于队列本身的特性先加入队列的状态总是先得到处理,这样就达到了一个目的:总是先将需要转移次数更少的状态进行分析处理,换句话说就是总是取得了这个状态的树中更接近根部的节点,又或者是总是让搜索树的广度得到尽可能增加。

在这个问题中,找到从起点到终点的最短路径其实就是一个建立队列的过程:

1.从起点开始,先将其加入队列,设置距离为0;

2.从队列首端取出位置,将从这个位置能够到达的位置加入队列,并且让这些位置的距离为上一个位置的距离加上1;

3.循环2直到将终点添加到队列中,这说明我们已经找到了路径;

注意到在这个过程中,每次处理的位置所对应的距离是严格递增的,因此一旦找到终点,当时的距离就是最短距离;

同样基于这个原因,搜索可移动到的位置所使用的判断条件中不仅仅是不碰墙壁、不超过边界,还有一个就是没有到达过,因为如果已经到达了这个位置,这说明已经有更短的路径到达这个位置,这次到达这个位置的路径是更差的,不可能得到更好的最终解。

#include<iostream>
#include<cstdio>
using namespace std;
const int INF = 100000000;
char map[3000][3000];
int d[3000][3000];
int mov[4][2] = {1,0,-1,0,0,1,0,-1};
int n,m,sx,sy,gx,gy;
pair <int,int> que[1010];
int bfs()
{
    int frt = 0,til = 0;
    for(int i = 0;i < n; i++)
    {
        for(int j = 0;j < m; j++)
        {
            d[i][j] = INF;
        }
    }
    que[til].first = sx;
    que[til++].second = sy;
    d[sx][sy] = 0;
    while(frt != til)
    {
        int nx = que[frt].first;
        int ny = que[frt++].second;
        if(nx == gx && ny == gy)
            break;
        for(int i = 0;i < 4; i++)
        {
            int x = nx + mov[i][0];
            int y = ny + mov[i][1];
            if(x >= 0 && x < n && y >= 0 && y < m && map[x][y] != '#' && d[x][y] == INF)
            {
                que[til].first = x;
                que[til++].second = y;
                d[x][y] = d[nx][ny] + 1;
            }
        }
    }
    return d[gx][gy];
}
int main()
{
    scanf("%d %d",&n,&m);
    getchar();
    for(int i = 0;i < n; i++)
    {
        scanf("%s",map[i]);
        getchar();
        for(int j = 0;j < m; j++)
        {
            if(map[i][j] == 'S')
            {
                sx = i;
                sy = j;
                continue;
            }
            if(map[i][j] == 'G')
            {
                gx = i;
                gy = j;
            }
        }
    }
    int res = bfs();
    res != INF ? printf("%d",res) : printf("-1");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao__hei__hei/article/details/84572740