Nightmare Ⅱ(逃离噩梦)【双向BFS】

>Link

HDOJ3085


>解题思路

由于有鬼的限制,我们需要开两个队列,一个记录男孩一个记录女孩,两个bfs同时进行,如果女孩走到了男孩走到过的地方,说明两个相遇了,这时所用时间就是答案

注意男孩一次可以走三步,女孩走一步,所以一次bfs,男孩需要处理三层,女孩处理一层


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define N 810
using namespace std;

const int xx[4] = {
    
    -1, 0, 0, 1}, yy[5] = {
    
    0, -1, 1, 0};
struct node
{
    
    
	int x, y;
};
int T, n, m, z[5][5], cntz, vis[N][N], ans;
bool mark[N][N];
char cc;
queue<node> q1, q2;

int read ()
{
    
    
	int l = 0; cc = getchar();
	while (cc < '0' || cc > '9') cc = getchar();
	while (cc >= '0' && cc <= '9') {
    
    l = l * 10 + cc - '0'; cc = getchar();}
	return l;
}
bool check (int x, int y, int w)
{
    
    
	if (x < 1 || x > n || y < 1 || y > m) return 0;
	if (mark[x][y]) return 0;
	if (abs (x - z[1][0]) + abs (y - z[1][1]) <= 2 * w) return 0;
	if (abs (x - z[2][0]) + abs (y - z[2][1]) <= 2 * w) return 0;
	return 1;
}
void work ()
{
    
    
	memset (vis, 0, sizeof (vis)); //记录男孩或女孩是否走过
	memset (mark, 0, sizeof (mark)); //记录墙
	cntz = ans = 0;
	while (!q1.empty()) q1.pop();
	while (!q2.empty()) q2.pop();
	
	n = read(), m = read();
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= m; j++)
	  {
    
    
	  	cc = getchar();
		while (cc != '.' && cc != 'Z' && cc != 'G'
		       && cc != 'M' && cc != 'X') cc = getchar();
		if (cc == 'X') mark[i][j] = 1;
		if (cc == 'Z') z[++cntz][0] = i, z[cntz][1] = j;
		if (cc == 'M') q1.push((node){
    
    i, j}), vis[i][j] = 1;
		if (cc == 'G') q2.push((node){
    
    i, j}), vis[i][j] = 2;
	  }
	while (!q1.empty() || !q2.empty())
	{
    
    
	    //vis不用清零,因为如果下一秒那个位置男孩or女孩不能达到了,check也会把它continue出来
		ans++; //每一秒
		node u, v;
		for (int t = 1; t <= 3; t++) //男孩三层(走三次)
		  for (int j = q1.size(); j >= 1; j--)
		  //这时的q1.size()不会循环一次改变一次,就可以把循环之前q1里面所有的(上一秒)都处理掉,十分巧妙
		  {
    
    
		  	u = q1.front(); q1.pop();
		  	if (!check (u.x, u.y, ans)) continue;
		  	for (int i = 0; i < 4; i++)
		  	{
    
    
		  		v = (node){
    
    u.x + xx[i], u.y + yy[i]};
		  		if (!check (v.x, v.y, ans) || vis[v.x][v.y] == 1)
				   continue;
 				if (vis[v.x][v.y] == 2) {
    
    printf ("%d\n", ans); return;}
				q1.push(v), vis[v.x][v.y] = 1;
			}
		  }
		for (int j = q2.size(); j >= 1; j--)
		{
    
    
			u = q2.front(); q2.pop();
		  	if (!check (u.x, u.y, ans)) continue;
			for (int i = 0; i < 4; i++)
			{
    
    
		  		v = (node){
    
    u.x + xx[i], u.y + yy[i]};
		  		if (!check (v.x, v.y, ans) || vis[v.x][v.y] == 2)
				   continue;
				if (vis[v.x][v.y] == 1) {
    
    printf ("%d\n", ans); return;}
				q2.push(v), vis[v.x][v.y] = 2;
			}
		}
	}
	printf ("-1\n");
}

int main()
{
    
    
	T = read();
	while (T--) work ();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/113105383