仙岛求药(BFS迷宫寻找最短路径)

描述 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。

下图 显示了一个迷阵的样例及李逍遥找到仙药的路线.

《仙岛求药(BFS迷宫寻找最短路径)》

输入 输入有多组测试数据. 每组测试数据以两个非零整数 M 和 N 开始,两者均不大于20。M 表示迷阵行数, N 表示迷阵列数。接下来有 M 行, 每行包含N个字符,不同字符分别代表不同含义: 

1) ‘@’:少年李逍遥所在的位置;

2) ‘.’:可以安全通行的方格;

3) ‘#’:有怪物的方格;

4) ‘*’:仙药所在位置。

当在一行中读入的是两个零时,表示输入结束。

输出 对于每组测试数据,分别输出一行,该行包含李逍遥找到仙药需要穿过的最少的方格数目(计数包括初始位置的方块)。如果他不可能找到仙药, 则输出 -1。 样例输入

8 8
.@##...#
#....#.#
#.#.##..
..#.###.
#.#...#.
..###.#.
...#.*..
.#...###
6 5
.*.#.
.#...
..##.
.....
.#...
....@
9 6
.#..#. 
.#.*.# 
.####. 
..#... 
..#... 
..#... 
..#... 
#.@.## 
.#..#. 
0 0

样例输出

10
8
-1

之前写了一个深搜,在做后面的题目时用深搜肯定超时超时超时,索性直接写个广搜,因为我感觉深搜好理解一些,一直遍历一直遍历找到最短的。广搜就直接遍历一次,使得下一次到达的点都是最小的。这样就很好的和队列(先进先出)结合起来。通俗的说就是到达一个点,这个点会同时走4个方向,但是深搜的话走一个方向只有到这条路没法走或者到终点才会返回上一个路口。从起点到终点就是建立队列的过程

1.从起点开始,先将其加入队列,设置步数为0

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

3.循环2直到从队列首端取出的是终点

最简单的理解方法就是画图,结合队列的先进先出,每到达一个点

#include<iostream>
#include<queue>
using namespace std;
typedef pair<int, int> P;
int n, m, q1, q2, z1, z2;
char a[21][21];
int pd(int i, int j){
	if (i < 0 || j < 0 || i >= n || j >= m || a[i][j] == '#')//不能出边界
		return 0;
	return 1;
}
int main(){
	while (1){
		int map[21][21];
		cin >> n >> m;
		if (n == 0 && m == 0)
			break;
		for (int i = 0; i < n; i++){
			for (int j = 0; j < m; j++){
				cin >> a[i][j];
				map[i][j] = 1000;
				if (a[i][j] == '@'){
					q1 = i; q2 = j;
				}
				if (a[i][j] == '*'){
					z1 = i; z2 = j;
				}
			}
		}
		queue<P> que;
		map[q1][q2] = 0;
		que.push(P(q1, q2));//将起点入队列
		while (que.size()) {
			P p = que.front(); //取得头元素
			que.pop();
			if (p.first == z1&&p.second == z2)
				break;
			if (pd(p.first + 1, p.second) && map[p.first + 1][p.second] == 1000){//如果地图上某一点已经走过了,那就不用走了,肯定有别的方法到达它更短
				map[p.first + 1][p.second] = map[p.first][p.second] + 1;//因为在每次处理的位置都是递增的。走过的路不用走了,也映证了广搜
				que.push(P(p.first + 1, p.second));
			}
			if (pd(p.first - 1, p.second) && map[p.first - 1][p.second] == 1000){
				map[p.first - 1][p.second] = map[p.first][p.second] + 1;
				que.push(P(p.first - 1, p.second));
			}
			if (pd(p.first, p.second + 1) && map[p.first][p.second + 1] == 1000){
				map[p.first][p.second + 1] = map[p.first][p.second] + 1;
				que.push(P(p.first, p.second + 1));
			}
			if (pd(p.first, p.second - 1) && map[p.first][p.second - 1] == 1000){
				map[p.first][p.second - 1] = map[p.first][p.second] + 1;
				que.push(P(p.first, p.second - 1));
			}
		}
		if (map[z1][z2] == 1000)
			printf("-1\n");
		else
			printf("%d\n", map[z1][z2]);
	}
	return 0;
}

先结合图理解代码。有好的思想一起交流


实在不懂了就可以先看下:抓住那头牛。这道题的广搜就简单很多
http://blog.csdn.net/qq_33193309/article/details/55260780

    原文作者:BFS
    原文地址: https://blog.csdn.net/qq_33193309/article/details/55260608
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞