【YBTOJ】【HDUOJ 3085】逃离噩梦

题目大意:

给定一张 (N imes M) 的地图,地图中有 (1) 个男孩,(1) 个女孩和 (2) 个鬼。

字符 . 表示道路,字符 X 表示墙,字符 M 表示男孩的位置,字符 G 表示女孩的位置,字符 Z 表示鬼的位置。

男孩每秒可以移动 (3) 个单位距离,女孩每秒可以移动 (1) 个单位距离,男孩和女孩只能朝上下左右四个方向移动。

在第 (k) 秒后所有与鬼的曼哈顿距离不超过 (2 imes k) 的位置都会被鬼占领。

每一秒鬼会先扩展,扩展完毕后男孩和女孩才可以移动。

求在不进入鬼的占领区的前提下,男孩和女孩能否回合,若能回合,求出最短会和时间。

(1<n,m<800)

正文:

双向 BFS 板子题。题目中的提示已经很足了。开两个队列分别搜男孩和女孩,就按着题目中给定的限制扩展即可。

代码:

const int N = 810;

inline int READ() {
	int x = 0, f = 1; char s = getchar();
	while (s < '0' || s > '9') { if (s == '-') f = -f; s = getchar(); }
	while (s >= '0' && s <= '9') { x = x * 10 + s - '0'; s = getchar(); }
	return x * f;
}

struct point
{
	int x, y;
}bs, gs;
int n, m, gx1, gx2, gy1, gy2;;
char a[N][N];
int vis[N][N];
int dx[4] = {0, 1, 0, -1},
    dy[4] = {1, 0, -1, 0};

queue <point> q, t;

bool ck(int x, int y, int k) {return x > 0 && x <= n && y > 0 && y <= m && a[x][y] != 'X' && a[x][y] != 'Z' && abs(x - gx1) + abs(y - gy1) > 2 * k && abs(x - gx2) + abs(y - gy2) > 2 * k;}

void bfs()
{
	memset (vis, 0, sizeof vis);
	while (!q.empty()) q.pop();
	while (!t.empty()) t.pop();
	q.push(bs), t.push(gs);
	vis[bs.x][bs.y] = 1, vis[gs.x][gs.y] = 2;
	for (int tim = 1; !q.empty() || !t.empty(); tim ++)
	{
		for (int j = 1; j <= 3; j++)
		{
			for (int k = q.size(); k--; )
			{
				point u = q.front();q.pop();
				if (!ck(u.x, u.y, tim)) continue;
				for (int i = 0; i < 4; i++)
				{
					int x = u.x + dx[i], y = u.y + dy[i];
					if (!ck(x, y, tim)) continue;
					if (vis[x][y] == 2)
					{
						printf ("%d
", tim);
						return;
					}
					if (vis[x][y]) continue;
					vis[x][y] = 1;
					q.push((point){x, y});
				}
			}
		}
		for (int k = t.size(); k--; )
		{
			point u = t.front();t.pop();
			if (!ck(u.x, u.y, tim)) continue;
			for (int i = 0; i < 4; i++)
			{
				int x = u.x + dx[i], y = u.y + dy[i];
				if (!ck(x, y, tim)) continue;
				if (vis[x][y] == 1)
				{
					printf ("%d
", tim);
					return;
				}
				if (vis[x][y]) continue;
				vis[x][y] = 2;
				t.push((point){x, y});
			}
		} 
	} 
	printf ("-1
");
}

int main()
{
	for(int t = READ(); t--; )
	{
		n = READ(), m = READ();
		memset (a, 0, sizeof a);
		gs = bs = (point){0, 0};
		gx1 = gx2 = gy1 = gy2 = 0;
		for (int i = 1; i <= n; i++)
		{
			scanf ("%s", a[i] + 1);
			for (int j = 1; j <= m; j++)
			{
				if (a[i][j] == 'M') bs.x = i, bs.y = j;
				if (a[i][j] == 'G') gs.x = i, gs.y = j;
				if (a[i][j] == 'Z') 
					if (!gx1) gx1 = i, gy1 = j;
					else gx2 = i, gy2 = j;
			}
		}
		bfs();
	}
	return 0;
}
原文地址:https://www.cnblogs.com/GJY-JURUO/p/14658891.html