迷宫的最短路径

题目来源

挑战程序设计竞赛(第二版)

语言

C/C++

题目

迷宫的最短路径

描述

给定一个大小为 N * M 的迷宫。迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格的通道移动。请求出从起点到终点所需要的最小步数。请注意,本题假定从起点一定可以移动到终点。

样例

输入:

N=10,M=10(迷宫如下所示。'#', '.', 'S', 'G' 分别表示墙壁、通道、起点和终点)

# S # # # # # # .  #

.  .  .  .  .  .  # .  .  #

.  # .  # # .  # # .  #
.  # .  .  .  .  .  .  .  .
# # .  # # .  # # # #

.  .  .  .  # .  .  .  .  #
.  # # # # # # # .  #
.  .  .  .  # .  .  .  .  .
.  # # # # .  # # # .

.  .  .  .  # .  .  . G #

输出:

22

思路

该题求最短路径,一般求最短路径、最少操作之类的题都应该想到宽度优先搜索(BFS),因为宽度优先搜索每次对当前结点所有可能达到的位置都遍历一遍,很符合最少的思想。尝试了一下宽度优先搜索,发现果然可以,宽度优先搜索的实现用到了队列的思想。

 

设置一个二维数组表示距离,用来记录每一步能到达的位置,用无穷大将数组初始化,代表刚开始所有的位置都无法到达。开始时将起点距离设置为 0,进行宽度优先搜索,最后检查终点位置的数值,若为无穷大则不能到达,否则该值为起点到终点的最短距离。

代码

#include 
#include 
#define MAX_N 100
#define MAX_M 100 

using namespace std;

const int INF = 1000000;	// 无穷大

// input
char maze[MAX_N][MAX_M] = {
	"#S######.#",
	"......#..#",
	".#.##.##.#",
	".#........",
	"##.##.####",
	"....#....#",
	".#######.#",
	"....#.....",
	".####.###.",
	"....#...G#",
}; 
int M = 10, N = 10;
int sx = 0, sy = 1;	// 起点坐标 
int gx = 9, gy = 8;	// 终点坐标 
// input end 

// code 
 struct point{	// 坐标 
	int x;
	int y;
};
int d[MAX_N][MAX_M];	// 到各个位置的最短距离的数组 
int dx[4] = {1, 0, -1, 0};	// 下、右、上、左 
int dy[4] = {0, 1, 0, -1};

int bfs();

int main() {
	int len = bfs();
	cout << len << endl;

	
	return 0;
}

// 求从  的最短距离
// 如果无法到达,则是 INF 
int bfs()
{
	queue que;
	// 把所有位置都初始化为 INF
	for (int i = 0; i < N; i++){
		for (int j = 0; j < M; j++){
			d[i][j] = INF;
		} 
	} 
	// 把起点加入队列,并把这一地点的距离设置为 0
	point p;
	p.x = sx;
	p.y = sy;
	que.push(p);
	d[sx][sy] = 0;
	
	// 不断循环直到队列长度为 0 
	while (que.size()){
		// 从队列前端取出元素
		point p_tem = que.front();
		que.pop();
		// 如果取出的状态已经是终点,则结束搜索
		if (p_tem.x == gx && p_tem.y == gy)
			break;
		// 四个方向循环
		for (int i = 0; i < 4; i++){
			// 移动之后的位置记为  
			int nx = p_tem.x + dx[i];
			int ny = p_tem.y + dy[i];
			// 判断是否可以移动以及是否已经访问过(d[nx][ny] != INF 即为访问过)
			if (maze[nx][ny] != '#' && nx >= 0 && nx < N
				 && ny >= 0 && ny < M && d[nx][ny] == INF){
				 	// 可以移动的话,则加入队列,并且到该位置的距离确定为到 p 的
					//  距离 +1
					point p_add;
					p_add.x = nx;
					p_add.y = ny;
					que.push(p_add);
					d[nx][ny] = d[p_tem.x][p_tem.y] + 1;
				 } 
		} 	 
	} 
	return d[gx][gy];
} 

时间复杂度0

最坏情况对整个 N * M 的数组遍历一次,因此时间复杂度为 O(N * M)。

所涉及的知识点

宽度优先搜索(BFS)

你可能感兴趣的:(数据结构与算法)