BFS算法——迷宫(蓝桥填空题)

目录

·【问题描述】

·【ac代码】

·【队列的概念和基本操作】

·【一些闲话】

【问题描述】

下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可以通行的地方。

010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这个它的上、下、左、右四个方向之一。

对于上面的迷宫,从入口开始,可以按 DRRURRDDDR 的顺序通过迷宫,一共 1010 步。其中 D、U、L、RD、U、L、R 分别表示向下、向上、向左、向右走。

对于下面这个更复杂的迷宫 (30 行 50 列),请找出一种通过迷宫的方式,其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。请注意在字典序中 D<L<R<UD<L<R<U。

测试代码文件:https://luogu.oss-cn-hangzhou.aliyuncs.com/upload/problem_attachment/c0dq3rm7.txt?response-content-disposition=attachment%3B%20filename%3D%22maze.txt%22&OSSAccessKeyId=LTAI4FsiWjpNs1epYQp3d1Ag&Expires=1712051270&Signature=8tLR7rDxf0AxXe5%2B1P3GNQ7U8Mk%3D

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000 
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

【ac代码】

该题是标准的BFS模板题,本站有很多优质帖子介绍BFS在此不多做赘述

#include <bits/stdc++.h>
using namespace std;
int m[30][50];//开辟一个二维数组存放10地图
bool vis[50][50];//记录当前x,y是否被访问过,访问过则标为1
int dir[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
//题目要求输出一条字典序最小的路径
//我们知道字典序d<l<r<u,因此按“下左右上”的顺序查找
char ch[]={'D','L','R','U'};
bool check(int x,int y)//判断函数,判断当前x,y是否合法
{
	if(x>=0&&x<=29&&y>=0&&y<=49)
	{
		return true;
		
	}
	return false;
}
struct Pos//结构体
{
	int x,y;//坐标
	string road;//字符串记录路径,在c++中字符串的连接可以直接相加
};
void bfs(int x,int y)
{
	Pos cur;//创建一个点,并初始化
	cur.x=0;
	cur.y=0;
	cur.road=" ";
    //创建队列,队列先进先出的性质决定它是实现BFS最好的容器
	queue<Pos> qu;
	qu.push(cur);//向队列中加入初始化好的首个结点
	vis[0][0]=1;//标记x=0,y=0点已被访问过,未来不能再进行访问
	while(!qu.empty())//如果队列不为空则一直循环,!是因为队列不为空时qu.empty()返回值是0
	{
		cur=qu.front();//取出当前队列中排在第一位的点
                       //为了方便用cur来接收,也可以新创建Pos型的变量来接收
		qu.pop();//一旦取出当前队列排在最前的点,立即删去该点,让下一个递补到最前一位
		if(cur.x==29&&cur.y==49)//如果到达出口,输出路径,结束循环,因为BFS找的是最短路径
		{
			cout<<cur.road<<endl;//体现了字符串的好处,如果用char数组接收,还要循环输出
			 break;
		}
		for(int i=0;i<4;i++)//如果没到出口,循环“下左右上”寻找
		{
			int nowx=cur.x+dir[i][0];//更新坐标
			int nowy=cur.y+dir[i][1];
            //check()函数检查下标是否越界
            //vis[][]检查该点是否查找过
            //m[][]检查此点是否是障碍点(该题定义1为障碍点,0为通行点)
			if(check(nowx,nowy)&&!vis[nowx][nowy]&&m[nowx][nowy]==0)
			{
				Pos pp;//创建一个Pos型的新变量接收更新后的坐标和路径
				pp.x=nowx;
				pp.y=nowy;
                pp.road=cur.road+ch[i];//字符串可以直接相加
				vis[nowx][nowy]=1;
				qu.push(pp);//将新点加入队列,此时该点属于队列的最后一位,因为队列是先进先出
			}
		}
		
	}
}
int main()
{
    //用freopen是因为所给测试用例中间没有空格,直接复制粘贴不能有效输入
    //用该函数可以实现文件内的数字单个读入,一定记得把路径改成自己电脑上的路径
	freopen("C:\\Users\\21396\\Downloads\\maze.txt","r",stdin);
	for(int i=0;i<30;i++)
	{
		for(int j=0;j<50;j++)
		{
			char a;//char类型接收
			cin>>a;
			m[i][j]=a-'0';//字符转化为整型,因为m二维数组用int开辟
		}
	}
	bfs(0,0);
	return 0;
}

【队列的概念和基本操作】

        queue是一种先进先出的数据结构,有两个出口,队列只允许从一端新增元素,从另一端移除元素。因为只有队头和队尾才能被外界使用,因此队列不允许遍历操作。

1)	qu.push(elem);//往队尾添加元素
2)	qu.pop();//从头移除一个元素
3)	数据类型 名称=qu.back();//返回最后一个元素
4)	数据类型 名称=qu.front();//返回队头元素
5)	int 名称=qu.empty();//非空返回0
6)	int 名称=qu.size();//判断队列大小

【一些闲话】

博主选择这道题来写,一是因为该题是BFS经典题型,另一原因是该题还涉及字符路径保存,用string来写比较方便。

欢迎各位dalao指出错误,提问,博主(bme专业)一定尽力解答

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值