广度优先搜索---迷宫问题(最短路径长度)
题目:
给定一个 n x m大小的迷宫,其中 “*” 代表不可通过的墙壁,而 ’.‘代表平地,S表示起点,T表示终点。移动过程中,如果当前位置是(x,y)(下标从0开始),且每次只能往上下左右四个方向的平地移动,求从起点S到达终点T的最少步数。
.....
.*.*.
.*S*.
.***.
...T*
在上面的样例中,S的坐标为(2,2),T的坐标为(4,3)。
输入格式:
第一行给出m,n,表示迷宫的行,列;
下面每一行给出 n个字符,共 m行;
最后一行给出起点坐标S1,S2,终点坐标T1,T2。
输出格式:
输出从起点S到达终点T的最少步数, 不存在输出 -1。
输入样例 1:
5 5
.....
.*.*.
.*S*.
.***.
...T*
2 2 4 3
输出样例 1:
11
输入样例 2:
5 5
.....
.*.*.
.*S*.
.***.
...T.
2 2 4 3
输出样例 2:
9
输入样例 3:
5 5
.....
.....
..S..
.....
...T.
2 2 4 3
输出样例 3:
3
直接上代码。。。BFS总的来说,比写的DFS代码多一些,奈何时间复杂度好,并且有模板,不容易出现死循环!!!。
1 #include<iostream> 2 #include<queue> 3 #include<unordered_map> 4 using namespace std; 5 6 const int maxn = 100,INF = 0x3fffffff; 7 struct Node { 8 int x,y; 9 int layer = 0;//记录从起点S到达该位置的最少步数(层数) 10 } node; 11 char maze[maxn][maxn]; 12 int m,n,MIN = INF; 13 int S1,S2,T1,T2; 14 int X[] = {0,0,1,-1};//控制访问的四个方向,新技能 get !!! 15 int Y[] = {1,-1,0,0}; 16 bool inque[maxn][maxn] = {false};//标记元素是否已经入队---这样不会改变矩阵原本的状态,新技能get !!! 17 bool judge(int i,int j) { 18 if(i < 0 || j < 0 || i>= m||j>= n || maze[i][j] == '*' || inque[i][j] == true) 19 return false; 20 return true; 21 } 22 void BFS(int i, int j) { 23 queue<Node> que; //定义队列 24 node.x = i,node.y = j,node.layer = 0; 25 que.push(node); //入队 26 inque[i][j] = true; //标记已经入队 27 while(!que.empty()) { //队列非空 28 Node top = que.front(); //取出队首元素 29 que.pop(); //队首元素出队 30 if(top.x == T1 && top.y == T2) { //如果能到达终点 T 31 MIN = top.layer; 32 break; 33 } 34 for(int i = 0; i < 4; ++i) { //访问相邻的四个元素 35 int nowI = top.x + X[i]; 36 int nowJ = top.y + Y[i]; 37 if(judge(nowI,nowJ)) { 38 node.x = nowI,node.y = nowJ,node.layer = top.layer + 1; 39 que.push(node); //入队 40 inque[nowI][nowJ] = true; //标记已经入队 41 } 42 } 43 } 44 } 45 46 int main() { 47 cin>>m>>n; 48 for(int i = 0; i < m; ++i) { //初始化迷宫 49 for(int j = 0; j < n; ++j) 50 cin>>maze[i][j]; 51 } 52 cin>>S1>>S2>>T1>>T2; //起点(S1,S2)和终点(T1,T2) 53 BFS(S1,S2); //广度优先搜索 54 cout<< (MIN <INF? MIN : -1); 55 return 0; 56 }
运行结果 1:
运行结果 2:
运行结果 3: