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;
}