【蓝桥杯】 算法提高 学霸的迷宫(深度优先搜索、BFS)—— 酱懵静
算法提高 学霸的迷宫
问题描述
学霸抢走了大家的作业,班长为了帮同学们找回作业,决定去找学霸决斗。但学霸为了不要别人打扰,住在一个城堡里,城堡外面是一个二维的格子迷宫,要进城堡必须得先通过迷宫。因为班长还有妹子要陪,磨刀不误砍柴功,他为了节约时间,从线人那里搞到了迷宫的地图,准备提前计算最短的路线。可是他现在正向妹子解释这件事情,于是就委托你帮他找一条最短的路线。
输入格式
第一行两个整数n,m,为迷宫的长宽。
接下来n行,每行m个数,数之间没有间隔,为0或1中的一个。0表示这个格子可以通过,1表示不可以。假设你现在已经在迷宫坐标(1,1)的地方,即左上角,迷宫的出口在(n,m)。每次移动时只能向上下左右4个方向移动到另外一个可以通过的格子里,每次移动算一步。数据保证(1,1),(n,m)可以通过。
输出格式
第一行一个数为需要的最少步数K。
第二行K个字符,每个字符∈{U,D,L,R},分别表示上下左右。如果有多条长度相同的最短路径,选择在此表示方法下字典序最小的一个。
样例输入
Input Sample 1:
3 3
001
100
110
Input Sample 2:
3 3
000
000
000
样例输出
Output Sample 1:
4
RDRD
Output Sample 2
4
DDRR
---分割线---
分析:
对于本题而言我们除了要找到最短路径之外,还多了一个额外的任务:输出该最短路径的行走轨迹。而对于路径相同的,又要输出字典序最小的。什么是字典序最小?你看样例输出2的结果嘛,为什么是DDRR而不是RRDD或者RDRD或者DRDR?
很简单,因为每次你走的时候(假设有多个方向可走),你都要保证当前你选择的方向在字典中的顺序是最小的{D<R<L<U}
其实这个设定,就是在暗示你,当你在写BFS时,那四个行走方向的顺序应该是DRLU。
回想在算法与数据结构——最经典的走迷宫最短路径算法(深度优先搜索BFS的典型实例)这道题的解题过程中,我用了一个结构体来实现数学中二维空间里的点(具有两个int型数,分别代表x坐标和y坐标)。那么同样地,在这道题里面,我们是不是也可以在这个结构体里面额外的增加一个string类型的变量,来保存从起点走到当前点的行走轨迹呢?再拓宽一点,我们是不是也可以连那个距离也一起封装进来呢?
废话不多说,下面直接上代码:
---分割线---
#include<iostream> #include<string> #include<queue> using namespace std; const int MAX_X=505,MAX_Y=505; //图的最大规格 int n,m; //目的地坐标 int map[MAX_X][MAX_Y]; //图 int vis[MAX_X][MAX_Y]; //对于某个点而言是否访问过的标记 int move[4][2]={{1,0},{0,-1},{0,1},{-1,0}}; //四种行走方式 char dir[4]={'D','L','R','U'}; //对应上面的四种行走方式(按字典序) struct Point{ //封装好了的结构体(点的抽象实现) int x,y,length; //分别表示坐标的(x,y)以及从起点到当前坐标的距离长度lenth string path; //封装进来的行走轨迹 Point(int a,int b){ x=a,y=b; } //构造函数 }; void bfs() { queue<Point> q; Point p(1,1); //初始化入口坐标 p.length=0,p.path=""; //初始化距离以及行走轨迹 vis[1][1]=1; //标记起点已经走过 q.push(p); //入队列 while(!q.empty()) //题目保证有终点,故可以这么设置循环条件 { Point p=q.front();q.pop(); //取第一个队列元素进行发散,并将其推出 int i; for(i=0;i<4;i++) //分别判断四种行走方式 { Point new_p(p.x+ move[i][0],p.y+ move[i][1]); if(new_p.x>0 && new_p.x<=n && new_p.y>0 && new_p.y<=m //判断未出边界 && map[new_p.x][new_p.y]!=1 && vis[new_p.x][new_p.y]==0) //判断可移动并且未走过 { vis[new_p.x][new_p.y]=1; //标记其已走过 new_p.length=p.length+1; //赋值为前一个路程长度加1 new_p.path=p.path+dir[i]; //添加轨迹 if(new_p.x==n&&new_p.y==m) //如果已经到了终点则直接退出循环 { cout<<new_p.length<<"\n"<<new_p.path<<endl; break; } q.push(new_p); //入队列 } } if(i!=4) break;//对于上面的退出作是否是非法退出的判断,是则表示找到了出口,直接退出全过程 } } int main() { string str; cin>>n>>m; for(int i=1;i<=n;i++) { cin>>str; for(int j=1;j<=m;j++) map[i][j]=str[j-1]-'0'; } bfs(); return 0; }
- 学霸的迷宫-蓝桥杯算法提高-广搜 bfs 经典问题
- 蓝桥杯算法提高——学霸的迷宫(bfs)
- 蓝桥杯 算法提高 学霸的迷宫 (BFS 路径存储)
- C++ - 蓝桥杯 - 算法提高 学霸的迷宫 (bfs+记录路径)
- 蓝桥杯-算法提高 学霸的迷宫(BFS-倒向追踪输出移动方向)
- 蓝桥杯 算法提高 学霸的迷宫(简单bfs+记录路径)
- 蓝桥杯 算法提高 学霸的迷宫 经典BFS问题
- 蓝桥杯_算法提高_学霸的迷宫(BFS方法)
- 算法笔记_107:蓝桥杯练习 算法提高 学霸的迷宫(Java)
- 蓝桥杯 算法提高 学霸的迷宫
- 蓝桥杯_算法提高_学霸的迷宫(简单回溯法,没有减枝)
- 蓝桥杯 算法提高 学霸的迷宫 【BFS + 记录路径 + 板子题】
- 蓝桥杯算法提高 -- 学霸的迷宫
- 算法提高 学霸的迷宫 蓝桥杯训练
- 蓝桥杯_ 算法提高 学霸的迷宫
- 算法提高 学霸的迷宫 蓝桥杯
- 蓝桥杯 算法提高 学霸的迷宫
- 蓝桥杯 算法提高 学霸的迷宫 JAVA
- 蓝桥杯 ADV-147 算法提高 学霸的迷宫
- 蓝桥杯 算法提高 学霸的迷宫(bfs+方向输出)