迷宫 BFS 计蒜客 2020 蓝桥杯省赛 B 组模拟赛(一)

思路:

求最短距离,肯定用宽搜BFS
这道题主要需要注意以下几个问题:
   1.可能起点就是终点
   2.可能起点就是传送门
   3.可能起点就有障碍物
   4.可能传送门的下一个点还是传送门

代码:

#include<bits/stdc++.h>
#define maxn 5050
using namespace std;
char grid[maxn][maxn];	//存储迷宫地图
int vis[maxn][maxn];	//记录每个位置是否被遍历过

struct node{	//用于宽搜的结构体
	int x, y, step; 
}; 

int main(){
	int n, m, q;
	int sx, sy, ex, ey;	//(sx, sy)为起点, (ex, ey)终点
	cin>>n>>m;
	//输入地图
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			cin>>grid[i][j];
			
	map<pair<int, int>, int> ma;//ma记录传送门起点, 如第一组数据2 2 2 4, ma[make_pair(2, 2)] = 1
	map<int, pair<int, int> > mb;//mb记录传送门终点, 相对应mb[1] = make_pair(2, 4) 
	int a, b, c, d, k = 1; //k记录传送门的个数, ma和mb的记录
	
	int dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0 ,1};
	memset(vis, 0, sizeof(vis));
		
	cin>>q;
	for(int i=0; i<q; i++){
		cin>>a>>b>>c>>d;
		ma[make_pair(a, b)] = k;
		mb[k++] = make_pair(c, d);
	}
	
	cin>>ex>>ey;
	sx = 1, sy = 1;
	
	//如果起点就是终点,直接返回0
	if(ex==1&&ey==1){
		cout<<1<<endl;
		return 0; 
	}
	
	//如果起点就有障碍物,则输出No solution(我也不知道会不会卡这个,反正写了总没错)
	if(grid[sx][sy]=='*'){
		cout<<"No solution";
		return 0;
	}
	
	//处理起点就是传送门的情况
	while(ma[make_pair(sx, sy)]){
		vis[sx][sy] = 1;
		int tx = sx, ty = sy;
		sx = mb[ma[make_pair(tx, ty)]].first;
		sy = mb[ma[make_pair(tx, ty)]].second;
	}
	
	//宽搜队列
	queue<node> que;
	node nd;
	nd.x = sx, nd.y = sy, nd.step = 0;
	que.push(nd);
	vis[sx][sy] = 1;
	
	while(que.size()){
		node t = que.front();
		que.pop();
		
		int x = t.x, y = t.y, step = t.step;
		
		//到达终点,直接输出距离
		if(x==ex && y==ey){
			cout<<step;
			return 0;
		}
		
		//如果过程中遇到障碍物,直接跳过
		if(grid[x][y] == '*')
			continue;
		
		//向四个方向搜索
		for(int i=0; i<4; i++){
			int nx = x + dx[i], ny = y + dy[i];
			
			if(nx>=1 && nx<=n && ny>=1 && ny<=m && grid[nx][ny]=='.' && !vis[nx][ny]){
				vis[nx][ny] = 1;
				//ma[{x, y}]大于0则表示该点为传送门
				if(ma[make_pair(nx, ny)]){
					//处理传送门下一个点还是传送门的情况
					while(ma[make_pair(nx, ny)]){
						int tx = nx, ty = ny;
						nx = mb[ma[make_pair(tx, ty)]].first;
						ny = mb[ma[make_pair(tx, ty)]].second;						
					} 
					
					//将不是传送门的点加入队列,注意这里不需要处理障碍点,前面已经处理了
					node d;
					d.x = nx, d.y = ny, d.step = step + 1; 
					que.push(d);
				}
				else{
					//不是传送门直接加入队列,不用处理传送门理由同上
					node d;
					d.x = nx, d.y = ny, d.step = step + 1; 					
					que.push(d);
				}
			}  
		} 
	}
	//宽搜结束还没到达终点,直接输出No solution
	cout<<"No solution";
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值