利用广度优先搜索(bfs)来解决迷宫问题
一.广度优先搜索(bfs)
1.什么叫bfs
广度优先搜索类似于树的层次遍历;
是利用队列的先进先出的特点来实现的;
通俗来说就是一次访问多条路,分层;
一般来说,广度搜索解决的问题主要为求最优解和最短路径。
2.遍历过程
(1)从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点v1,v2…vi;
(2)分别从这些邻接点出发依次访问它们的邻接点。按照v1,v2…vi的次序(先被访问的顶点的邻接点先于后被访问的顶点的邻接点),访问每一个顶点的所有未被访问过的邻接点。
(3)依次类推,直到图中所有已被访问的顶点的邻接点都被访问到。
第一层 | 第二层 | 第三层 | 第四层 |
---|
bfs:v–>v1–>v2–>v3–>v4–>v5–>v6–>v7
遍历过程结束;
因为广度搜索遍历是一层一层的去搜索从入口到出口的遍历过程,所以在找到出口的时候,一定是当前最短路径;
3.算法设计
解决的问题:
(1)如何确定一个顶点是否访问?
设置一个vis[]数组,vis[i]为0就表示没有被访问,vis[i]为1就表示i点已经被访问过。(根据实际情况,如迷宫图,也可以在图上面直接记录修改)
(2)如何找到正确的从出口到入口的路径
所有搜索过的方块都在队列中,
最后通过队列找出从 出口=>入口的一条迷宫路径;
同时设置一个pre指针来指向每一个前路径;例如:
迷宫图(墙为0,路为1,从(1,1)到(5,6))
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 1 1 0 0
层数 | i | j | pre |
---|---|---|---|
>0 | 1 | 1 | -1 |
>1 | 1 | 2 | 0 |
>2 | 1 | 3 | 1 |
3 | 1 | 4 | 2 |
>4 | 2 | 3 | 2 |
5 | 1 | 5 | 3 |
>6 | 3 | 3 | 4 |
7 | 2 | 5 | 5 |
>8 | 4 | 3 | 6 |
9 | 3 | 2 | 6 |
>10 | 5 | 3 | 8 |
11 | 3 | 1 | 9 |
>12 | 5 | 4 | 10 |
13 | 4 | 1 | 11 |
>14 | 5 | 5 | 12 |
15 | 5 | 1 | 13 |
>16 | 5 | 6 | 14 |
4.bfs算法模板
void bfs(int x1,int y1)
{
建造队列q;
入口入队;
while(队列不为空)
{
访问队首元素;
队首元素出队;
if(到达目标位置)
{
输出;
}
相邻结点入队;
置为已访问;
}
}
二.代码
#include<stdio.h>
#include<string.h>
#define maxsize 1000
int map[maxsize][maxsize];
int head,tail;
int next[4][2]={{0,1},{-1,0},{1,0},{0,-1}}; //行走路径顺序:下,左,右,上;
int x1,y1,x2,y2; //(x1,y1)入口,(x2,y2)出口
int w,h;
bool flag;
struct node
{
int x; //列;
int y; //行;
int pre; //指向下一个元素的指针
}q[maxsize];
void print(int p)//添加路径输出递归模型
{
if(p==-1)return ;//递归出口
print(q[p].pre);//非尾部递归 ,用于正向输出路径
printf("(");
printf("%d,%d",q[p].x,q[p].y);
printf(")\n");
}
//输出;
int bfs(int m,int n)
{
head=0;
tail=1;
q[tail].x=m;
q[tail].y=n;
q[tail].pre=-1;//设置起始位置
while(head<tail)
{
head++;
for(int i=0;i<4;i++)
{
int x=q[head].x+next[i][0];
int y=q[head].y+next[i][1];
if(x>=1&&x<=w&&y>=1&&y<=h&&map[y][x]==0)
{
tail++;
q[tail].x=x;
q[tail].y=y;
q[tail].pre=head;
map[y][x]=-1;
if(x==x2&&y==y2) //找到目标点,输出,并返回;
{
print(tail);
flag=true;
return 0;
}
}
}
}
return 0;
}
int main()
{
scanf("%d%d",&w,&h);
/* for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
scanf("%d",&map[i][j]);*/
char str;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
{
scanf(" %c",&str);
if(str=='1')
map[i][j]=1;
else
map[i][j]=0;
}
//两种不同的输入,10地图和#.的地图输入
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
flag=false;
bfs(x1,y1);
if(!flag)
printf("到不了");
return 0;
}
假如要输出最短时间的话,就增加一个变量k;如:
struct node
{
int x; //列;
int y; //行;
int k; //最短时间;
}
//然后初始化k的值为0;
....
q[head].k=0;
....
//然后每一层+1;
....
q[tail].k=q[head].k+1;
....
//输出的时候就是:
printf("%d",q[tail].k);