迷宫的最短路径问题(BFS)

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

(N,M<=100)

样例输入:

10 10

# S # # # # # # . #
. . . . . . # . . #
. # . # # . # # . #
. # . . . . . . . .
# # . # # . # # # #
. . . . # . . . . #
. # # # # # # # . #
. . . . # . . . . .
. # # # # . # # # .
. . . . # . . . G #

样例输出:

22

分析:像最短路径,最少操作之类的问题可以使用宽度优先搜索。

关于宽度优先搜索:

宽度优先搜索按照距开始状态由近及远的顺序进行搜索,那么它是怎么做到的呢?

搜索时首先将初始状态加到队列里,此后从队列的最前段不断取出状态(所以每次处理的都是离初始状态最近的),把从该状态可以转移到的状态中尚未访问过的部分加入队列,如此往复,直至队列被取空或找到了问题的解。

回到本题加深一下对宽度优先搜索的理解:

1、本题的状态是所在位置的坐标,所以可以构造pair来表示状态。

2、因为要求最小步数,所以想到用一个数组d[N][M]把移动时的步数记下来。

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

4、循环3直到从队列首端取出的是终点,这说明我们已经找到了路径

注:每次处理的位置所对应的步数是严格递增的,所以,如果已经到达过这个位置不用再向这个位置走,因为再走一遍还是到这个位置那么这个路径的步数肯定比上一次到达这个位置的路径的步数多,所以才能实现一旦找到终点,当时的步数就是最小步数。

5、所以要将已经访问过的状态标记出来,用充分大的常数INF初始化数组d,到达的位置会有步数,没到达的则是INF.

画了个不是很严谨的图,对着代码看下一应该很好理解,通过图发现只有最短路径被延续下去直到终点。

代码如下:

#include <iostream>
#include <stdio.h>
#include <queue>
#define MAX_N 100
#define MAX_M 100
using namespace std;
const int INF = 100000000;
typedef pair<int,int> P;
char maze[MAX_N][MAX_M+1];
int N,M;
int sx,sy;
int gx,gy;
int d[MAX_N][MAX_M];
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
void bfs();
int main()
{
    scanf("%d%d",&N,&M);
    for(int i=0;i<N;i++){
        scanf("%s",maze[i]);
    }
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(maze[i][j]==‘S‘)
            {
                sx=i;
                sy=j;
            }
            if(maze[i][j]==‘G‘){
                gx=i;
                gy=j;
            }
        }
    }
    bfs();
printf("%d",d[gx][gy]);
    return 0;
}

void bfs(){
    queue<P> que;
    for(int i;i<N;i++){
        for(int j=0;j<M;j++){
            d[i][j]=INF;
        }
    }
    que.push(P(sx,sy));
    d[sx][sy]=0;
    while(que.size()){
    //从队列的最前端取出元素
    P p=que.front(); que.pop();
        if(p.first==gx&&p.second==gy)break;
    for(int i=0;i<4;i++){
            int nx=p.first+dx[i],ny=p.second+dy[i];
            if(maze[nx][ny]!=‘#‘&&nx>=0&&nx<N&&ny>=0&&ny<M&&d[nx][ny]==INF){
                que.push(P(nx,ny));
                d[nx][ny]=d[p.first][p.second]+1;
            }
        }

    }
}
时间: 2024-10-13 03:07:45

迷宫的最短路径问题(BFS)的相关文章

迷宫的最短路径(BFS的简单应用)

[题目简述]:给定一个大小为n*m的迷宫.迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格的通道移动.请求出起点到终点所需的最小步数.(注:本题假定从起点一定可以移动到终点) 如图: #S######.# ......#..# .#.##.##.# .#........ ##.##.#### ....#....# .#######.# ....#..... .####.###. ....#...G# [分析]:广度优先搜索是由近及远的搜索,所以在这个问题中采用BFS很合适,只要注意访问过的位

编程算法 - 迷宫的最短路径 代码(C++)

迷宫的最短路径 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 给定一个大小为N*M的迷宫. 迷宫由通道和墙壁组成, 每一步可以向邻接的上下左右四格的通道移动. 请求出从起点到终点所需的最小步数. 请注意, 本题假定从起点一定可以移动到终点. 使用宽度优先搜索算法(DFS), 依次遍历迷宫的四个方向, 当有可以走且未走过的方向时, 移动并且步数加一. 时间复杂度取决于迷宫的状态数, O(4*M*N)=O(M*N). 代码: /* * m

数据结构之迷宫问题求解(二)迷宫的最短路径

上篇文章我们讨论了,迷宫问题的普通求解问题,这篇文章我们继续深入,求迷宫的最短路径. 要想求迷宫的最短路径,一个很简单的方法就是再设置一个Min栈,用来放最短路径,每找到一个出口,就将path栈与Min栈进行比较,如果path栈更小,则赋值给Min. 而在上篇文章中,我们将走过的路径做了标记,每走一个坐标,就把那个坐标置为3,直至找到出口. 因此如果用这种标记方式,显然是会出现问题的. 所以我们需要换种标记方式! 最终....我决定,使出口的值为2,每走一步使当前位置标记变为是上一位置标记再加1

POJ3984 迷宫问题【水BFS】

#include <cstdio> #include <cmath> #include <iostream> #include <algorithm> #include <cstdlib> #include <cstring> #include <map> #include <vector> using namespace std; map<string,int>mymap; map<stri

迷宫的最短路径 (BFS)

N*M的迷宫,从起点到终点,求最短距离 宽度优先搜索按照距开始状态由近及远的顺序进行搜索,因此可以很容易的用来求最短路径,最少操作之类问题的答案.  (可以构造成pair或者编码成int来表达状态) 当状态更加复杂时,就需要封装成一个类来表示状态了. 虽然到达终点时就会停止搜索,可如果继续下去直到队列为空的话,就可以计算出各个位置的最短距离.此外,如果搜索到最后,d依然为INF的话,便可得知这个位置就是无法从起点发到达的位置. 1 const int INF = 100000000; 2 3 t

BFS求解迷宫的最短路径问题

题目:给定一个大小为N*M的迷宫,迷宫由通道('.')和墙壁('#')组成,其中通道S表示起点,通道G表示终点,每一步移动可以达到上下左右中不是墙壁的位置.试求出起点到终点的最小步数.(本题假定迷宫是有解的)(N,M<=100) 输入: 10 10#S######.#......#..#.#.##.##.#.#........##.##.####....#....#.#######.#....#......####.###.....#...G# 输出: 22 本题目与解题思路均来源于挑战程序设计

POJ 3984 迷宫问题(简单bfs+路径打印)

传送门: http://poj.org/problem?id=3984 迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33105   Accepted: 18884 Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个

深度优先搜索(迷宫救人最短路径)

1 import java.util.Scanner; 2 3 public class One { 4 //n,m为迷宫的行列范围,p,q是某人迷路所在地点,min用于记录走到终点最小路径的步数 5 public static int n,m,p,q,min=9999; 6 //数组a是迷宫,1代表有障碍物,数组d用于移动方向(右.下.左.上),数组book用于标记当前位置是否在路径中 7 public static int a[][]=new int[51][51],book[][]=new

逃离迷宫(HDU 1728 BFS)

逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 21384    Accepted Submission(s): 5180 Problem Description 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方