使用BFS求最小步数

bfs宽度优先搜索经常用于求最短路径长度,许多的最短路径算法都是基于该思想。

迷宫寻宝

洪尼玛今天准备去寻宝,在一个n*n (n行, n列)的迷宫中,存在着一个入口、一些墙壁以及一个宝藏。由于迷宫是四连通的,即在迷宫中的一个位置,只能走到与它直接相邻的其他四个位置(上、下、左、右)。现洪尼玛在迷宫的入口处,问他最少需要走几步才能拿到宝藏?若永远无法拿到宝藏,则输出-1。

多组测试数据。

每组数据输入第一行为正整数n,表示迷宫大小。

接下来n行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'#'表示该位置为墙壁,字符'S'表示该位置为入口,字符'E'表示该位置为宝藏,输入数据中只有这四种字符,并且'S'和'E'仅出现一次。

n≤1000

 Output

输出拿到宝藏最少需要走的步数,若永远无法拿到宝藏,则输出-1。

 Sample Input

5 S.#.. #.#.# #.#.# #...E #....

 Sample Output

7

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std; 
char map[1001][1001];
int vis[1001][1001];
int n, dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };
int x11, y11, x22, y22, flag;
struct point
{
	int x;
	int y;
}tmp1,tmp2;
int main()
{
	queue<point> q;
	while (scanf("%d", &n) != EOF)
	{
		while (!q.empty())
		q.pop();
		flag = 0;
		memset(vis, 0, sizeof(vis));
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				cin >> map[i][j];
				if (map[i][j] == 'S')          //记录起始结束的点
				{
					x11 = i; y11 = j;
				}
				if (map[i][j] == 'E')
				{
					x22 = i; y22 = j;
				}
			}
		}
		tmp1.x = x11, tmp1.y = y11;           //头点入队并标记
		q.push(tmp1); vis[tmp1.x][tmp1.y] = 1;
		while (!q.empty())
		{
			tmp1 = q.front(); q.pop();
			if (tmp1.x == x22&&tmp1.y == y22) //如果到达终点,记录的步数一定是最小的!
			{
				flag = 1; break;
			}
			for (int i = 0; i < 4; i++)       //四个方向走
			{
				tmp2.x = tmp1.x + dx[i]; tmp2.y = tmp1.y + dy[i];
				if (tmp2.x >= 1 && tmp2.x <= n && tmp2.y >= 1 && tmp2.y <= n && vis[tmp2.x][tmp2.y] == 0 && map[tmp2.x][tmp2.y] != '#')
				{
					vis[tmp2.x][tmp2.y] = vis[tmp1.x][tmp1.y] + 1;  //如果符合要求该点步数是上一点步数加1,加入队伍
					q.push(tmp2);
				}
			}
		}
		if (flag)
			cout << vis[x22][y22] -1 << endl;
		else
			cout << "-1" << endl;
	}
	return 0;
}

迷宫问题

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 32406   Accepted: 18515

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表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample Input

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

Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

一道普通的BFS问题,但所求不是最短步数而是最短路径,那么需要一个二维记录数组来记录这个位置的点的上一个位置。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std; 
int map[10][10], vis[10][10], dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };
struct point
{
	int x;
	int y;
}tmp1,tmp2;
point pre[10][10], ans[100];
int main()
{
	while (scanf("%d%d%d%d%d", &map[0][0], &map[0][1], &map[0][2], &map[0][3], &map[0][4]) != EOF)
	{
		queue<point> q;
		memset(vis, 0, sizeof(vis));
		for (int i = 1; i < 5; i++)
			for (int j = 0; j < 5; j++)
				cin >> map[i][j];
		tmp1.x = 0; tmp1.y = 0;                  //把起点压入队列中并标记
		q.push(tmp1); vis[0][0] = 1;
		while (!q.empty())
		{
			tmp1 = q.front(); q.pop();
			if (tmp1.x == 4 && tmp1.y == 4)
				break;
			for (int i = 0; i < 4; i++)
			{
				tmp2.x = tmp1.x + dx[i]; tmp2.y = tmp1.y + dy[i];
				if (tmp2.x >= 0 && tmp2.x < 5 && tmp2.y >= 0 && tmp2.y < 5 && vis[tmp2.x][tmp2.y] == 0 && map[tmp2.x][tmp2.y] == 0)
				{
					vis[tmp2.x][tmp2.y] = vis[tmp1.x][tmp1.y] + 1;
					q.push(tmp2);
					pre[tmp2.x][tmp2.y].x = tmp1.x;           //记录这个点的前一个位置
					pre[tmp2.x][tmp2.y].y = tmp1.y;
				}
			}
		}
		int lastx = 4, lasty = 4, num = 0;                    //从终点开始不断向前找位置
		while (lastx!=0 || lasty!=0)
		{
			ans[num].x = lastx;
			ans[num++].y = lasty;
			int box1 = lastx, box2 = lasty;
			lastx = pre[box1][box2].x;
			lasty = pre[box1][box2].y;
		}
		cout << "(0, 0)" << endl;
		for (int i = num - 1; i >= 0; i--)
			printf("(%d, %d)\n", ans[i].x, ans[i].y);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/slience_646898/article/details/81156583