寒假集训_专题一题解_G - BFS (Gym - 101755H)

#[译文](https://codeforces.com/gym/101755/problem/H)H。每个测试的安全路径时间限制每个测试2秒的内存限制256 MB输入标准输入输出标准输出播放新的RPG。其中的世界地图由n×m个单元的网格表示。停留在某个单元格中的任何游戏角色都可以从该单元格向四个方向移动-移至垂直,右侧,向前和向后的单元格,但不会离开世界地图。

怪物生活在一些细胞中。如果在某个时刻,您所在某个怪物能以d步尼尔短距离到达的牢房中,他会立即冲向您并杀死您。

您必须从游戏领域的一个单元活到另一个单元。确定是否可能,如果可以,请找到执行此操作所需的最少步骤。

输入第一行包含三个非负整数n,m和d(2≤n·m≤200000,0≤d≤200000)—地图的大小和怪物危险的最大距离。

接下来的n行中的每行包含m个字符。这些字符可以等于«。»,«M»,«S»和«F»,分别表示空单元格,带有怪兽的单元格,开始单元格和结束单元格。开始和结束单元格为空,并且在输入中仅显示一次。

输出如果可以从起始单元格到结束单元格恢复活力,则输出执行此步骤所需的最少步骤。否则,输出«-1»。

Examples
input
5 7 1
S.M…M


M…M…
…F
output
12
input
7 6 2
S…
…M…

…M

M…
…F
output
11
input
7 6 2
S…
…M…


…M
M…
…F
output
-1
input
4 4 2
M…
.S…

…F
output
-1

题目大意

有一个n×m的网格,其中有一些怪兽W,还有一个怪兽能一次能走的步数r,问是否存在一种走法,走过的路径不能被怪兽一次走到,且步数最短,求最短步数

题解

分析

把不能走的路径标记好,bfs一遍

注意点

1.需要用一维数组来模拟二维数组,可写一个函数(trans)转化
2.不能走的路径也可以用数学方法来的得出,但会TLE,必须用bfs
3.r=0的边界情况
4.bfs时可能(听说)需要先标记再入列,否则会MLE

代码

#include<iostream>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
const int N = 2e5+10;
int dx[4] = {0,0,1,-1}, dy[4] = {1,-1,0,0},m,n;
char op[N];
bool st[N];
struct node
{
	int x,y;
	int step;
}master,tmp;
queue <node> q;
int trans(int x, int y)
{
	return x*m + y;
} 
void bfs1()
{
	while(q.size())
	{
		node t = q.front();
		q.pop();
		if(!t.step)continue;
		int x = t.x,y=t.y;
		for(int i = 0; i < 4; i ++)
		{
			int tx = x+dx[i], ty = y+dy[i];
			if(tx>=0&&tx<n&&ty>=0&&ty<m&&!st[trans(tx,ty)])
			{
				node t2;
				t2.x=tx,t2.y=ty,t2.step=t.step-1;
				q.push(t2);
				st[trans(tx,ty)] = true;
			}
		}
	}
}
int main()
{
	int r;
	bool flag = true;
	node S,M,F;
	cin >> n >> m >> r;
	for(int i = 0; i < n; i ++)
	{
		scanf("%s",op);
		for(int j = 0; j < m; j ++)
		if(op[j] == 'S'){
		S.x=i;
		S.y=j;
		S.step = 0;
		}
		else if(op[j] == 'F'){
			F.x=i;F.y=j;
		}
		else if(op[j] == 'M'){
			master.x=i;
			master.y=j;
			master.step = r;
			st[trans(i,j)] = 1;
			q.push(master);
		}
	}
	bfs1();
/*  	不用BFS  会TLE
	for(int i = 0; i < cnt; i ++)
		for(int x = min(n-1,master[i].x+r); x>=0 && x >= master[i].x-r; x--)
			for(int t = abs(x-master[i].x),y = min(m-1,master[i].y+r-t); y>=0&&abs(y-master[i].y)+t<=r; y --)
				st[trans(x,y)] = true;
*/
				
	if(st[trans(S.x,S.y)]||st[trans(F.x,F.y)])
	{
		printf("-1\n");
		return 0;
	}
 	tmp = S;
 	q.push(tmp);
 	st[trans(S.x,S.y)]= true;
 	while(q.size())
 	{
 		node t = q.front();
 		q.pop();
		for(int i = 0; i < 4; i++)
		{
			int tx = t.x+dx[i], ty = t.y+dy[i];
			if(tx>=0&&tx<n&&ty>=0&&ty<m&&!st[trans(tx,ty)])
			{
				if(tx == F.x && ty == F.y)
				{
					printf("%d\n",t.step+1);
					flag = false;
				}
				st[trans(tx,ty)] = true;
				tmp.x = tx;
				tmp.y = ty;
				tmp.step = t.step + 1; 				q.push(tmp); 			} 		} 		如果(标志!)休息; 	} 	if(flag)printf(“-1”); 	返回0; } ` ` `








 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值