使用BFS解决迷宫问题(边权相等)

来看一道模板题
acwing 884.走迷宫
给定一个n×m的二维整数数组,用来表示一个迷宫,数组中只包含0或1,其中0表示可以走的路,1表示不可通过的墙壁。
最初,有一个人位于左上角(1,1)处,已知此人每次可以向上下左右任何一个方向移动一个位置。
请问:该人从左上角移动到右下角(n,m)处,至少需要移动多少次。
数据保证(1,1)和(n,m)处的数字为0,且至少存在一条通路。
输入格式:
第一行包括两个整数n,m。
接下来n行包括m个整数(0或者1),表示完整的二维数组迷宫。
输出格式:
输出一个整数,表示从左上角到右上角的最少移动次数。
数据范围:
1<=n,m<=100
输入样例:
5 5
01000
01010
00000
01110
00010
输出样例:
8
#include<iostream>
#include<cstring> // memset
#include<queue>
using namespace std;
int n,m;
int Map[110][110];
int From[110][110];
queue<pair<int,int>>q; // 使用队列维护 

void bfs(int a,int b)
{
	q.push({a,b});
	while(!q.empty()) // 队列不空,即还有可以走的点 
	{
		pair<int,int>Start =q.front(); 
		q.pop(); 	// 读取这个数的值,并弹出队列
		Map[Start.first][Start.second]=1; // 表示已经用过
		// 上 (0,-1) 下 (0,1) 左 (-1,0) 右 (1,0)
		int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
		// 不使用这种方法也可以进行四次判断 
		for(int i=0;i<4;i++)
		{
			int x=Start.first+dx[i];
			int y=Start.second+dy[i];
			// [x][y] 为走过的点 
			if(Map[x][y]==0)
			{
				Map[x][y]=1;
				From[x][y]=From[Start.first][Start.second]+1; // 更新距离
				q.push({x,y}); 				
			}
		}
		
	}
	cout<<From[n][m];
}

int main()
{
	memset(Map,1,sizeof(Map)); // 这里将迷宫四周初始化为墙,省去越界判断 
	
	cin>>n>>m;
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>Map[i][j];
		}		
	}
		
	bfs(1,1);
	
	return 0; 
}

整体思路:

从起点开始宽搜遍历地图,当地图遍历完,就求出了起点到终点的距离.

 借用一下大佬的图Orz

一些刚开始不懂的点:

1.函数体中使用两个数组存储了四次移动的改变量,dx存储四种移动的横向变化,dy存储纵向的变化.

这种方法代替了四次判断,即:

void bfs(int a,int b)
{
	q.push({a,b});
	while(!q.empty()) // 队列不空,即还有可以走的点 
	{
		pair<int,int>Start =q.front(); 

		q.pop(); 	// 读取这个数的值,并弹出队列

		Map[Start.first][Start.second]=1; // 表示已经用过

		// 进行四次判断 

		int x=Start.first;
		int y=Start.second;
					 
		if(Map[x][y+1]==0) // 下 
		{
			Map[x][y+1]=1;
			From[x][y+1]=From[Start.first][Start.second]+1;
			q.push({x,y+1}); 
		}

		if(Map[x][y-1]==0) // 上
		{
			Map[x][y-1]=1;
			From[x][y-1]=From[Start.first][Start.second]+1;
			q.push({x,y-1}); 
		}

		if(Map[x-1][y]==0) // 左
		{
			Map[x-1][y]=1;
			From[x-1][y]=From[Start.first][Start.second]+1;
			q.push({x-1,y});
		}

		if (Map[x+1][y]==0) // 右
		{			
            Map[x+1][y]=1;
			From[x+1][y]=From[Start.first][Start.second]+1 ;
			q.push({x+1,y});
		}
			

	}
	cout<<From[n][m];

}

2.使用memset将迷宫越界的部分化为1(也就是墙),省去了越界判断这一步,否则需要在判断时加上此人在迷宫内这一条件。

memset(*数组名q,数值x,个数n)   通俗来讲时: 将q中n个数变为x;

3.关于循环队列queue

声明:

queue<int>q;        queue<pair<int,int>>q;   

使用:

push 从队尾插入        pop 从队头弹出        front 返回队头元素

back 返回队尾元素        empty 是否为空        size    长度

4.pair是STL中的模板类型,可以存储两个元素,被称为对组,是二元结构体的替代品,相当于:

struct pair{

typename1 first;

typename2 second;

}

这对值可以有不同的数据类型(T1,T2),两个值可以分别用first和second访问(点操作符)。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值