利用广度优先搜索(bfs)来解决迷宫问题

利用广度优先搜索(bfs)来解决迷宫问题

一.广度优先搜索(bfs)

1.什么叫bfs

广度优先搜索类似于树的层次遍历
是利用队列的先进先出的特点来实现的;
通俗来说就是一次访问多条路,分层;
一般来说,广度搜索解决的问题主要为求最优解和最短路径

2.遍历过程

(1)从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点v1,v2…vi;
(2)分别从这些邻接点出发依次访问它们的邻接点。按照v1,v2…vi的次序(先被访问的顶点的邻接点先于后被访问的顶点的邻接点),访问每一个顶点的所有未被访问过的邻接点。
(3)依次类推,直到图中所有已被访问的顶点的邻接点都被访问到。

第一层第二层第三层第四层
出发v
v1
v2
v3
v4
v5
v6
结束v7

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

层数ijpre
>011-1
>1120
>2131
3142
>4232
5153
>6334
7255
>8436
9326
>10538
11319
>125410
134111
>145512
155113
>165614

在这里插入图片描述

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);
  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值