BFS——龙舌兰酒吧

7 龙舌兰酒吧 (100 分)

有一个大小为n*m的矩形小镇,城镇上有房屋(“#”表示无法通过),有空地(“.”表示可通行),每次移动只能朝上下左右四个方向,且需花费1单位时间。

一天,二乔和承太郎约定在龙舌兰酒吧见面,两人同时从各自所在位置向酒吧出发。请问最少需要过多少时间他们才能在酒吧碰面。

地图上P表示二乔的位置,W表示承太郎的位置,B表示酒吧的位置。

输入格式:

第一行包含两个整数n,m,表示城镇的大小。(1<=m,n<=1000)。

接下来n行,每行m个字符,表示小镇的情况。

输出格式:

输出两人在酒吧碰面的最少花费时间,如果无法在酒吧碰面则输出-1。

输入样例:

5 4
.W.#
P#..
....
B..#
#...

输出样例:

4

思路:一开始运用递归来做

但是发现会超时,这是这周的最后一题,这题的上一题,找宝藏我是用递归来做没超时

但是这题超时了,因此采用队列来实现BFS,

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <stack>
#include <queue>
#define P pair<int, int>//将坐标封装成点便于后边队列的遍历
using namespace std;
char map[1005][1005];//地图大小,不要小于1000
struct jojo{//jojo对象来存放jo太郎和二乔的位置
	int x0;
	int y0; 
}p1,w1;//
int direc[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};//用来后面进行广度遍历上下左右节点
const int edge = 999999;//设置无限远
int rep = 0,rew = 0;
int xb=0,yb=0;//终点酒吧坐标
int n,m;
int bfs(jojo jo)//bfs实现
{
	queue<P> temp;
	int i,j;
	int dis[1005][1005];
	for(i = 0;i<n;i++)
	for(j = 0;j<m;j++)
	dis[i][j] = edge;//将起点到各点的距离初始化为无穷 

	temp.push(P(jo.x0,jo.y0));
	dis[jo.x0][jo.y0] = 0;//设置起点出发距离为0;
	//然后放入队列之中; 
	while(temp.size())
	{
		P t = temp.front();
		temp.pop();
		//将首元素移出队列
		if(t.first==xb&&t.second==yb)break;//如果到达终点
		for(i = 0;i<4;i++)
		{
			int dx = t.first+direc[i][0];
			int dy = t.second+direc[i][1];//记录移动之后的坐标(dx,dy)
			//上下左右 
			//判断是否已经访问过,如果dis[dx][dy]不为edge就是已经访问过了
			if(dx>=0&&dx<n&&dy>=0&&dy<m&&map[dx][dy]!='#'&&dis[dx][dy]==edge) 
			{
				temp.push(P(dx,dy));
				dis[dx][dy] = dis[t.first][t.second]+1;
			}
		 } 
	 } 
	return dis[xb][yb];//返回到酒吧的距离
}
int main()
{
      
	  cin>>n>>m;
	  int arr[2][2];
	  for(int i =0;i<n;i++)
	  for(int j = 0;j<m;j++)
	  {
	  	cin>>map[i][j];
		if(map[i][j]=='P')
		{
			p1.x0 = i;
			p1.y0 = j;
		}else if(map[i][j]=='W')
		{
			w1.x0 = i;
			w1.y0 = j;
		}
		
}

	rep = bfs(p1);//第一个人的距离
	rew = bfs(w1);	//第二个人的距离
	if(rep==edge||rew==edge) cout <<"-1"<<endl;//如果无法到达,酒吧位置上的距离仍然为无限远
	else cout<<max(rep,rew)<<endl;//如果可以到达,取最大值
	  return 0;
	  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值