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

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

输入:

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

输出:

22

       本题目与解题思路均来源于挑战程序设计竞赛(第二版),是个经典的将BFS与队列(先进先出)特性紧密结合问题。广度优先搜索(BFS)按照距开始状态由近及远的顺序进行搜索,因此很容易地用来求最短路径、最少操作之类的问题。我们可以用所在的位置表状态,转移的方式为四方向移动,只要将已经访问过的状态用标记管理起来,就可以很好地做到由近及远的搜索。由于要求最短距离,不妨用dis[n][m]数组把最短距离保存起来,初始用非常大的常熟inf来初始化它,这样尚未到达的的位置就是inf,也就同时起了标记的作用。虽然到达终点时就会停止搜索,可如果继续下去直到队列为空的话,就可以计算出到各个位置的最短距离。此外,若搜索到最后,dis依然为inf,便可得知这个位置是无法从起点到达。

附上代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 using namespace std;
 5 typedef pair<int,int> pa;
 6 const int inf=0x3f3f3f3f;
 7 char map[105][105];  //表示迷宫的字符串数组 
 8 int n,m;
 9 int sx,sy;   //起点坐标 
10 int gx,gy;   //终点坐标 
11 int dis[105][105];  //保存起点到各点最短距离 
12 queue<pa> q;
13 const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};  //表示x和y可以移动的四个方向 
14 int bfs()
15 {
16     for(int i=0;i<n;i++){
17         for(int j=0;j<m;j++){
18             dis[i][j]=inf;   //将起点到各点的距离初始化为无穷大,表示为到达 
19         }
20     }
21     q.push(pa(sx,sy));
22     dis[sx][sy]=0;  //从起点出发将距离设为0 ,并放入队列 
23     //不断循环直到队列的长度为0 
24     while(q.size())
25     {
26         //取出队首元素 
27         pa p=q.front();
28         q.pop();
29         //如果取出的状态是终点,则结束搜索 
30         if(p.first==gx&&p.second==gy) break;
31         //四个方向的循环 
32         for(int i=0;i<4;i++)
33         {
34             //移动之后的坐标记为(dx,dy) 
35             int dx=p.first+dir[i][0];
36             int dy=p.second+dir[i][1];
37             //判断是否已经访问过,如果dis[dx][dy]不为inf即为已经访问过 
38             if(dx>=0&&dx<n&&dy>=0&&dy<m&&map[dx][dy]!='#'&&dis[dx][dy]==inf)
39             {
40                 //可以移动的话,则加入到队列,并且该位置的距离确定为到p的距离加1 
41                 q.push(pa(dx,dy));
42                 dis[dx][dy]=dis[p.first][p.second]+1;
43             }
44         }
45      }
46      return dis[gx][gy]; 
47 }
48 int main()
49 {
50     cin>>n>>m;
51     getchar();
52     for(int i=0;i<n;i++){
53         for(int j=0;j<m;j++){
54             scanf("%c",&map[i][j]);
56             if (map[i][j] == 'S')
57             {
58                 sx=i; sy=j;
59             }
60             if (map[i][j] == 'G')
61             {
62                 gx=i; gy=j;
63             }
64             }
getchar();
65 } 66 int ans=bfs(); 67 cout<<ans<<endl; 68 return 0; 69 } 70 /* 71 10 10 72 #S######.# 73 ......#..# 74 .#.##.##.# 75 .#........ 76 ##.##.#### 77 ....#....# 78 .#######.# 79 ....#..... 80 .####.###. 81 ....#...G# 82 22 83 */

 

posted @ 2018-07-13 08:42  两点够吗  阅读(1736)  评论(0编辑  收藏  举报