2020寒假集训专题一搜索G题 Gym - 101755H 题解

2020寒假集训专题一搜索G题 Gym - 101755H 题解

原题链接:http://codeforces.com/gym/101755/problem/H
专题链接:https://vjudge.net/contest/347799#problem/G


思路很简单,先对怪兽bfs,把怪兽的统制范围标记出来(可以覆盖出入口),然后在bfs路径即可。

难点1,没有分别给出n,m的范围,而是给了n*m的范围,这里采用以一维数组模拟二维数组的方法。
难点2,但本题丧病的测试数据对bfs的效率有很高的要求。

代码如下

#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<string>
using namespace std;
int N, M, X;
int ans = 0;
int nx, ny;
int k;
char map[200001];
int f[5][2] = { {0,0}, {0,1}, {0,-1}, {-1,0},{1,0} };//对应上下左右四个方向
struct Node//x,y代表横纵坐标,co代表迭代数 
{
	int x, y,co;
}t,u;
queue <Node> que;
void bfs()//对怪兽bfs,将统治范围以'm'标记
{
	while (que.size())
	{
		u = que.front();
	     que.pop();	
		if (u.co+1 > X) continue;
		for ( k = 1; k <= 4; k++)
		{
			nx = u.x + f[k][0];
			ny = u.y + f[k][1];
			if ((nx <= N - 1) && (nx >= 0) && (ny <= M - 1) && (ny >= 0))
			{
				if (map[nx * M + ny] == '.' || map[nx * M + ny] == 'F' || map[nx * M + ny] == 'S')
				{
                   map[nx * M + ny] = 'm';//!
					t.x = nx;
					t.y = ny;
					t.co = u.co + 1;
					que.push(t);//!注意打上!的这两行,一定要先标记再加入队列,否则会MLE
				}
			}
		}
	}
};
void bfs1()//最短路径的bfs没什么好说的
{
	while (que.size())
	{
		u = que.front();
		que.pop();
		for ( k = 1; k <= 4; k++)
		{
			nx = u.x + f[k][0];
			ny = u.y + f[k][1];
			if ((nx <= N - 1) && (nx >= 0) && (ny <= M - 1) && (ny >= 0))
			{
				if (map[(nx)* M + (ny)] == '.')
				{
					map[(nx)* M + (ny)] = '*';
					t.x = nx;
					t.y = ny;
					t.co = u.co + 1;
					que.push(t);
				}
				else if (map[(nx)* M + (ny)] == 'S')
				{
					ans = u.co + 1;
					return ;
				}
			}
		}
	}
}
int main()
{
	cin >> N >> M >> X;
	for (int i = 0; i <= N - 1; i++)
	{
		getchar();
		for (int j = 0; j <= M - 1; j++)
		{
			scanf("%c", &map[i * M + j]);
		}
	}
	for (int i = 0; i <= N - 1; i++)
	{
		for (int j = 0; j <= M - 1; j++)
		{
			if (map[i * M + j] == 'M')
			{
				t.x = i;
				t.y = j;
				t.co = 0;
				que.push(t);
			}
		}
	}
                bfs();//!这里一定要一起bfs,不能找到一个M就bfs一个,否则会wa,原因暂时不明
	for (int i = 0; i <= N - 1; i++)
	{
		for (int j = 0; j <= M - 1; j++)
		{
			if (map[i * M + j] == 'F')
			{
				t.x = i;
				t.y = j;
				t.co = 0;
				que.push(t);
				bfs1();
				if (ans == 0)
					printf("-1\n");
				else
					printf("%d\n", ans);
				return 0;
			}
		}
	}
	printf("-1\n");
	return 0;
}

关于先标记再入队和先入队再标记的区别,建议看看https://www.cnblogs.com/Chierush/p/3624276.html

发布了6 篇原创文章 · 获赞 0 · 访问量 197

猜你喜欢

转载自blog.csdn.net/bllovepigpig/article/details/103963802