问题描述
下图给出了一个迷宫的平面图,其中标记为1的为障碍,标记为0的为可以通行的地方。
迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这个它的上、下、左、右四个方向之一。
对于上面的迷宫,从入口开始,可以按DRRURRDDDR的顺序通过迷宫,一共10步。其中D、U、L、R分别表示向下、向上、向左、向右走。
对于下面这个更复杂的迷宫(30 行50列),请找出一种通过迷宫的方式,其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。
请注意在字典序中D<L<R<U。
【输入】
题目解析
因为迷宫只有30行50列,所以暴力搜索是个不错的选择。如果数据量大的话,可能超时。BFS(Breadth-First Search,宽度优先搜索或广度优先搜索)是求最短路径的一种经典算法。
接下来我们要考虑两个问题:
-
如何保证路径最短?
BFS的特点是:它是逐层扩散的(往BFS的队列中加入邻居结点时,是按距离起点远近的顺序加入的:先加入距离起点为1的邻居结点,加完之后,再加入距离为2的邻居结点,等等),搜完一层,才会继续搜下一层。一条路径是从起点开始,沿着每一层逐步往外走,每多一层,路径长度就增加了1。那么,所有长度相同的最短路径都是从相同的层次扩散出去的。当搜到第一个到达终点的最短路径后,继续搜索,会返回其他可能不是最短的路径。
所以这题采用BFS,先搜到的肯定就是最短的路径了。 -
如何保证字典序最小?
因为字典序优先顺序为D<L<R<U,所以在每一层搜索的时候,先搜索D,然后依次搜索L、R、U,这样就可以保证先搜到的肯定是字典序最小的。
C++代码
#include<bits/stdc++.h>
using namespace std;
struct node
{
int x;
int y;
};
char a[31][51]; //存储地图二维数组
char k[4] = {'D','L','R','U'}; //四个方向
int dir[4][2] = {{1,0},{0,-1},{0,1},{-1,0}}; //与k数组对应方向的坐标加减
int vis[30][50]; //标记数组
char pre[31][51]; //记录前驱结点
void print_path(int x,int y) //打印路径从(0,0)到(29,49)
{
if(x==0&&y==0) return; //回溯到了起点,递归结束返回
if(pre[x][y]=='D') print_path(x-1,y); //回溯到向上的结点
if(pre[x][y]=='L') print_path(x,y+1); //回溯到向右的结点
if(pre[x][y]=='R') print_path(x,y-1); //回溯到向左的结点
if(pre[x][y]=='U') print_path(x+1,y); //回溯到向下的结点
cout<<pre[x][y]; //最后打印的是终点
}
void bfs() //队列实现宽度优先搜索
{
node now,next;
queue<node> q;
now.x = 0;
now.y = 0;
vis[now.x][now.y] = 1; //当前节点为已遍历
q.push(now);
while(!q.empty())
{
now = q.front();
q.pop();
if(now.x==29&&now.y==49) //第一次到达终点这就是字典序中最小的最短路径
{
print_path(29,49); //打印路径,从终点回溯到起点,但是打印出来是从起点到终点
return;
}
for(int i=0;i<4;i++)
{
next.x = now.x+dir[i][0];
next.y = now.y+dir[i][1];
if(next.x<0||next.x>29||next.y<0||next.y>49) continue; //越界
if(vis[next.x][next.y]==1||a[next.x][next.y]=='1') continue; //已经搜索过或当前点有障碍
vis[next.x][next.y] = 1; //此点搜索过
pre[next.x][next.y] = k[i]; //记录点(x,y)的前驱
q.push(next);
}
}
}
int main()
{
for(int i=0;i<30;i++) cin>>a[i]; //按行读地图数据
bfs(); //宽度优先遍历
}
正确答案
DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR