BFS求解迷宫问题并输出路线(C语言)
1.问题的提出
用二维矩阵表示一个迷宫,0表示可通行,1表示有障碍,请给出最短路径的路线。
给出迷宫:
[0,0,1,0;
0,0,0,0
0,1,1,0
0,1,0,0]
(0,0)为起始点,(3,3)为终点
2.问题求解的思路
题目要求求得最短路径,显然要用BFS的方法求解。
3.BFS
广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略。因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,因此得名。一般可以用它做什么呢?一个最直观经典的例子就是走迷宫,我们从起点开始,找出到终点的最短路程,很多最短路径算法就是基于广度优先的思想成立的。
在广度优先搜索算法中,解答树上结点的扩展是按它们在树中的层次进行的。首先生成第一层结点,同时检查目标结点是否在所生成的结点中,如果不在,则将所有的第一层结点逐一扩展,得到第二层结点,并检查第二层结点是否包含目标结点,……,对层次为n+1的任一结点进行扩展之前,必须先考虑层次完层次为n的结点的每种可能的状态。因此,对于同一层结点来说,求解问题的价值是相同的,可以按任意顺序来扩展它们。通常采用的原则是先生成的结点先扩展。
4.如何存储最短路径
这也是我在求解BFS问题的中遇到的最大的问题,在查阅资料后,我选择了记录每一个节点的前驱节点,然后再回溯的方法作为我们的解决方案。
我选择了用数组的方法记录每一个节点的前驱节点:
int route[4][4][2];
(route[i][j][0],route[i][j][1])表示(i,j)的前驱节点。
5.具体代码
#include<stdio.h> #include<stdlib.h> #include<stack> #include<queue> using namespace std; int record[4][4] = {0}; int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; int maze[4][4] = {{0,0,1,0}, {0,0,0,0}, {0,1,1,0}, {0,1,0,0}}; stack <int> s; int visit(int a,int b) { if(record[a][b] == 0&&maze[a][b] == 0&&a >= 0&&a <= 3&&b >= 0&&b <= 3) { return 1; } else { return 0; } } /*void traverse() { int len = s.size()/2; int b[15][2]; for(int i = len;i > 0;i--) { b[i][1] = s.top(); s.pop(); b[i][0] = s.top(); s.pop(); } for(int i = 1;i < len;i++) { printf("(%d,%d)->",b[i][0],b[i][1]); } printf("(%d,%d)",b[len][0],b[len][1]); printf("已到达终点!"); } void DFS(int maze[4][4],int start[2],int end[2]) { int p[2]; p[0] = start[0]; p[1] = start[1]; record[start[0]][start[1]] = 1; if(start[0] == end[0]&&start[1] == end[1]) { traverse(); exit(0); } for(int i = 0;i < 4;i++) { int x,y; x = start[0] + dir[i][0]; y = start[1] + dir[i][1]; if(visit(x,y)) { s.push(x); s.push(y); p[0] = x; p[1] = y; DFS(maze,p,end); } } s.pop(); s.pop(); }*/ void printRoute(int route[4][4][2],int start[2],int end[2]) { int i = end[0]; int j = end[1]; while(1) { printf("(%d,%d)<-",i,j); int a = route[i][j][0]; int b = route[i][j][1]; i = a; j = b; if(i == start[0] && j == start[1]) { break; } } printf("(%d,%d)",i,j); } void BFS(int maze[4][4],int start[2],int end[2]) { queue<int> que; que.push(start[0]); que.push(start[1]); int route[4][4][2] = {0}; while(que.empty() == false) { int i = que.front(); que.pop(); int j = que.front(); que.pop(); if(i == end[0]&&j == end[1]) { printRoute(route,start,end); printf("已找到终点!"); break; } if(visit(i+dir[0][0],j+dir[0][1])) { record[i+dir[0][0]][j+dir[0][1]] = 1; que.push(i+dir[0][0]); que.push(j+dir[0][1]); route[i+dir[0][0]][j+dir[0][1]][0] = i; route[i+dir[0][0]][j+dir[0][1]][1] = j; } if(visit(i+dir[1][0],j+dir[1][1])) { record[i+dir[1][0]][j+dir[1][1]] = 1; que.push(i+dir[1][0]); que.push(j+dir[1][1]); route[i+dir[1][0]][j+dir[1][1]][0] = i; route[i+dir[1][0]][j+dir[1][1]][1] = j; } } } int main() { int start[2] = {0,0}; int end[2] = {3,3}; /*s.push(start[0]); s.push(start[1]); DFS(maze,start,end); printf("无法到达终点"); */ BFS(maze,start,end); return 0; }
6.运行结果