搜索_BFS_双向BFS_HDOJ3085_Nightmare Ⅱ

版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84317162

点此打开题目页面

思路分析:

    考虑对男孩和和女孩各自使用BFS, 男孩的解空间树每次搜索三层对应男孩每秒钟可走三步, 女孩的解空间树每次搜一层, 对应女孩每秒钟可走一步, 同时注意第k秒时, 所有与初始两个鬼的曼哈顿距离不超过2k均被鬼覆盖, 下面给出基于此思想的AC代码:

//HDOJ3085_Nightmare Ⅱ
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
#include <algorithm>
#define mp make_pair
#define fi first
#define se second
using namespace std; 
typedef pair<int, int> pii;
const int MAX = 805, INF = 0x3f3f3f3f, dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
char G[MAX][MAX]; int n, m;
int bx, by, gx, gy, zx1, zy1, zx2, zy2;//男孩, 女孩, 鬼1, 鬼2的起始位置 
bool b[MAX][MAX], g[MAX][MAX];//[i][j]为true表示i行j列已被处理, 为false未被处理 
int main(){
	int T; scanf("%d", &T);
	while(T--){
		scanf("%d %d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%s", G[i] + 1);	
		//初始化男孩, 女孩, 鬼1, 鬼2起始位置
		zx1 = 0; 
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j){
				if(G[i][j] == 'M') bx = i, by = j, G[i][j] = '.';
				if(G[i][j] == 'G') gx = i, gy = j, G[i][j] = '.';
				if(G[i][j] == 'Z' && !zx1) zx1 = i, zy1 = j, G[i][j] = '.';
				if(G[i][j] == 'Z' && zx1) zx2 = i, zy2 = j, G[i][j] = '.';
			}
		memset(b, false, sizeof(b)), memset(g, false, sizeof(g)); 
		queue<pii> bq, gq;//男孩, 女孩的队列
		bq.push(mp(bx, by)), bq.push(mp(INF, INF)), b[bx][by] = true; 
		gq.push(mp(gx, gy)), gq.push(mp(INF, INF)), g[gx][gy] = true;
		int ti = 0, res = INF;//ti当前时间 
		while(++ti, bq.size() >= 2 || gq.size() >= 2){
			//搜索bq中的三层
			for(int i = 1; i <= 3 && !bq.empty(); ++i){
				while(!bq.empty()){
					int x = bq.front().fi, y = bq.front().se; bq.pop();		
					if(x == INF) break;
					if(abs(x - zx1) + abs(y - zy1) <= 2 * ti 
					   || abs(x - zx2) + abs(y - zy2) <= 2 * ti) continue;
					for(int j = 0; j <= 3; ++j){
						int u = x + dx[j], v = y + dy[j];
						if(u >= 1 && u <= n && v >= 1 && v <= m && G[u][v] == '.' && !b[u][v] 
								  && abs(u - zx1) + abs(v - zy1) > 2 * ti
								  && abs(u - zx2) + abs(v - zy2) > 2 * ti){
							if(g[u][v]){
								res = ti; goto P1;
							}
							b[u][v] = true, bq.push(mp(u, v));
						}
					}
				}
				bq.push(mp(INF, INF)); 
			} 
			//搜索gq中的一层
			while(!gq.empty()){
				int x = gq.front().fi, y = gq.front().se; gq.pop();
				if(x == INF) break;
				if(abs(x - zx1) + abs(y - zy1) <= 2 * ti 
				   || abs(x - zx2) + abs(y - zy2) <= 2 * ti) continue;
				for(int j = 0; j <= 3; ++j){
					int u = x + dx[j], v = y + dy[j];
					if(u >= 1 && u <= n && v >= 1 && v <= m && G[u][v] == '.' && !g[u][v]
					          && abs(u - zx1) + abs(v - zy1) > 2 * ti
							  && abs(u - zx2) + abs(v - zy2) > 2 * ti){
						if(b[u][v]){
							res = ti; goto P1;
						}	  	
						g[u][v] = true, gq.push(mp(u, v));	  	
					}					
				}		
			} 		
			gq.push(mp(INF, INF));
		}
		P1: if(res == INF) cout << -1 << endl; else cout << res << endl;		
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/solider98/article/details/84317162