[ABC317E] Avoid Eye Contact 题解

原题链接

题意简述

给定一张\(N\times M\)的地图,其中 . 表示空的可通行点,# 表示障碍,S表示起点,G表示终点,^,v,<,>表示观察者,其中观察者的视线范围为:从当前观察者所在的位置,按箭头所示方向,直到下一个边界或非空点间,形成的一条宽为 1 的矩形。

问从起点开始,在不暴露在观察者的视线中的情况下,到达终点,所需的最少步数。

\(2\le N,M \le 2000\)

做法分析

如果不存在观察者的话,是一个 BFS 的板题。

现在的问题是如何处理视线范围。

其实对于视线范围,我们可以理解为另一种障碍,提前预处理出每个点是否在观察者的视野内即可。

对于每个点flag[i][j][x]分别表示第 i 行,第 j 列的点是否处在第 x 种观察者的视线内。

我们设a[i][j]表示地图上第 i 行,第 j 列的点类型。

  • a[i][j] = '.',则flag[i][j][0] = flag[i - 1][j][0],若a[i][j] = 'v',则flag[i][j][0] = 1

  • a[i][j] = '.',则flag[i][j][1] = flag[i + 1][j][1],若a[i][j] = '^',则flag[i][j][1] = 1

  • a[i][j] = '.',则flag[i][j][2] = flag[i][j - 1][2],若a[i][j] = '>',则flag[i][j][2] = 1

  • a[i][j] = '.',则flag[i][j][3] = flag[i][j + 1][3],若a[i][j] = '<',则flag[i][j][3] = 1

最后统计时,若一个点的标记四种类型中有的一个带有标记,则该点无法通行。

预处理时间复杂度为\(O(NM)\), BFS 的时间复杂度也为\(O(NM)\),总复杂度为\(O(NM)\)

代码

#include <bits/stdc++.h>
#define ll long long
#define inf 2000000000
using namespace std;

int n, m;
char a[2010][2010];
int dis[2010][2010];
int flag[2010][2010][4];
int stx, sty, edx, edy;

queue<pair<int,int>> q;

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, 1, -1};

void bfs()
{
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			dis[i][j] = inf;
	q.push(make_pair(stx, sty));
	dis[stx][sty] = 0;
	while(!q.empty())
	{
		auto now = q.front();
		q.pop();
		if(now.first == edx && now.second == edy) return;
		for(int i = 0; i <= 3; i++)
		{
			int x = now.first + dx[i];
			int y = now.second + dy[i];
			if(x <= 0 || y <= 0 || x > n || y > n) continue;
			if(dis[x][y] != inf) continue;
			if(a[x][y] == '#') continue;
			if(flag[x][y][0] || flag[x][y][1] || flag[x][y][2] || flag[x][y][3]) continue;
			dis[x][y] = dis[now.first][now.second] + 1;
			q.push(make_pair(x, y));
		}
	}
}

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			cin >> a[i][j];
			if(a[i][j] == 'S')
				stx = i, sty = j;
			if(a[i][j] == 'G')
				edx = i, edy = j;
		}
	}
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			if(a[i][j] == '.') flag[i][j][0] = flag[i - 1][j][0];
			else if(a[i][j] == 'v') flag[i][j][0] = 1;
			
	for(int i = n; i >= 1; i--)
		for(int j = 1; j <= m; j++)
			if(a[i][j] == '.') flag[i][j][1] = flag[i + 1][j][1];
			else if(a[i][j] == '^') flag[i][j][1] = 1;
			
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			if(a[i][j] == '.') 	flag[i][j][2] = flag[i][j - 1][2];
			else if(a[i][j] == '>') flag[i][j][2] = 1;
			
	for(int i = 1; i <= n; i++)
		for(int j = m; j >= 1; j--)
			if(a[i][j] == '.') flag[i][j][3] = flag[i][j + 1][3];
			else if(a[i][j] == '<') flag[i][j][3] = 1;
			
	bfs();
	if(dis[edx][edy] == inf)
		printf("-1");
	else printf("%d", dis[edx][edy]);
	
	return 0;
}
posted @ 2023-08-27 07:49  six_one  阅读(35)  评论(0编辑  收藏  举报