迷宫探险(BFS)

题目:https://ac.nowcoder.com/acm/contest/61132/H

在与boss的最终决战之后,小蓝来到了冒险的最后一关,在他面前有一个n*m的迷宫,迷宫中道路用’.’表示,墙壁则由‘#’表示。小蓝初始在[1,1]的位置,他只有到达[n,m]才能开启最终的宝藏。小蓝现在迫不及待的想要开启宝藏,所以他想最短的时间内走出迷宫。现在迷宫内有一种特殊的装置 –“弹射器”。弹射器的格子用’*’表示。当走到有弹射器的一格时,小蓝必须选择一个方向,弹射器会让他沿着这个方向弹射 x个距离,不同弹射器的弹射距离可以不同。弹射后的格子如果超过迷宫边界或者是墙壁则不能选择这个方向。小蓝现在可以向上下左右四个方向走,每走一个格子需要消耗一个单位时间,弹射则不消耗时间。求最短需要多少时间小蓝才能走出迷宫。如果无法到达终点,输出-1。

弹射器的数量,位置和弹射距离将在输入中给出。起点和终点一定不是弹射器。

输入描述:

第一行两个整数 n, m,接下来n行,每行m个只包含’ . ’ , ’ * ’ , ’ # ’的字符描绘迷宫。

接下来一行一个整数k,下面的k行每行三个整数x, y, w表示在[x,y]格子的弹射器能弹射的距离。(2≤n≤3000,2≤m≤3000, n*m≤500000, 0≤k, w在int范围内

输出描述:

一行一个整数

示例1

输入

3 2

.*

#.

..

1

1 2 2

输出

1

示例2

输入

2 2
.*
#.
1
1 2 2

输出

-1

 总结:

BFS基本模板

本题关键在标记发射器及发射距离

代码献上(BFS)

#include <iostream>
#include<algorithm>
#include<queue>

using namespace std;

const int N=3e3+5;

int n,m,k,i,j;

int sum[N][N];                     //移动次数
int dist[N][N];                    //弹射发射器
char a[N][N];                      //地图
int dx[4]={0,0,1,-1};              //上下移动
int dy[4]={1,-1,0, 0};

int main()
{
	int x,y,w;
	cin>>n>>m;
	for(i=1;i<=n;i++)                                       //地图输入
    {
		for(j=1;j<=m;j++)
        {
			cin>>a[i][j];
		}
	}
    
	cin>>k;
	for(i=1;i<=k;i++)                                       //弹簧
    {
		cin>>x>>y>>w;
		dist[x][y]=w;
	}
    
	queue<pair<int,int> >q;                                  //建立栈
    
	q.push({1,1});
    
	while(q.size())
    {
		auto t=q.front();          
        q.pop();                                             //出栈
        
		x=t.first;y=t.second;                                
        
		int time=dist[x][y]==0?1:0;                          //自身位置
        
		for(i=0;i<4;i++)
        {
			int xx,yy;
			if(dist[x][y]==0)                                //判断该位置是否为弹射器
            {
                xx=x+dx[i],yy=y+dy[i];                       //上下位置移动
            }
			else                                             //位置为弹簧器
            {
                xx=x+dx[i]*dist[x][y],yy=y+dy[i]*dist[x][y]; //弹射器弹射
            }
            
			if(xx<1||xx>n||yy<1||yy>m||a[xx][yy]=='#')       //判断移动后位置是否为墙壁
                continue;                                    //跳过
            
			if(sum[xx][yy]&&sum[xx][yy]<=sum[x][y]+time)     //判断移动后是否已经经过
                continue;                                    //跳过
            
			sum[xx][yy]=sum[x][y]+time;                      //标记移动次数
			q.push({xx,yy});                                 //入栈
		}
	}
    
	if(sum[n][m])cout<<sum[n][m];                            //判断终点位置是否
	else cout<<-1;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值