HDU3085NightmareII题解--双向BFS

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=3085

分析

大意就是一个男孩和一个女孩在网格里,同时还有两个鬼,男孩每轮走三步,女孩每轮走一步,与鬼曼哈顿距离不超过2*轮数的区域都被鬼占领,问男孩女孩最少多少轮相遇?

这题显然用双向BFS,男孩每轮拓展3次,女孩每轮拓展1次,一个记录女孩走过哪些地方,另一个记录男孩,有个地方被两人都走过就输出答案

然后一开始我就发现我的BFS写得代码又臭又长,后面看一位大佬博客才学到简洁的操作

代码

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <iostream>
#define ll long long 
#define ri register int
using std::min;
using std::max;
using std::swap; 
using std::queue;
template <class T>inline int abs(int  x){
	return x<0?-x:x;
}
template <class T>inline void read(T &x){
	x=0;int ne=0;char c;
	while(!isdigit(c=getchar()))ne=c=='-';
	x=c-48;
	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
	x=ne?-x:x;return ;
}
const int maxn=805;
const int inf=0x7fffffff;
const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int g[maxn][maxn];
int n,m,T;
int sx,sy,tx,ty;
int gx1,gx2,gy1,gy2;
char str[maxn];
struct Dat{
	int x,y;
	Dat (int _x,int _y){x=_x,y=_y;}
	Dat () {x=y=0;}
};
int cnt=1,dis;
bool wtf=0;
bool vis1[maxn][maxn],vis2[maxn][maxn];
bool check(int x,int y){
	//if(wtf)printf("** %d %d %d %d %d %d\n",x,y,cnt,dis,abs(x-gx1)+abs(y-gy1),abs(x-gx2)+abs(y-gy2));
	if(x>=1&&x<=n&&y>=1&&y<=m&&g[x][y]!=1&&(abs(x-gx1)+abs(y-gy1))>dis&&(abs(x-gx2)+abs(y-gy2))>dis)return 1;
	return 0;
}
inline void bfs(){
	int x,y,xx,yy;
	int x1,x2,x3,y1,y2,y3,x4,y4;
	queue <Dat> q1,q2;
	while(q1.size())q1.pop();
	while(q2.size())q2.pop();
	q1.push(Dat(sx,sy));
	q2.push(Dat(tx,ty));
	cnt=1,dis=2;
	int l1=1,r1=1,l2=1,r2=1,lst=0;
	memset(vis1,0,sizeof(vis1));
	memset(vis2,0,sizeof(vis2));
	vis1[sx][sy]=vis2[tx][ty]=1;
	while(q1.size()&&q2.size()){wtf=0;			
		for(ri k=1;k<=3;k++){
			lst=r1;		
			while(l1<=lst){
				x=q1.front().x,y=q1.front().y;q1.pop();
				l1++;
				if(!check(x,y))continue;
				//printf("1 %d %d\n",x,y);
				for(ri i=0;i<4;i++){
					xx=x+dx[i],yy=y+dy[i];
					if(!check(xx,yy)||vis1[xx][yy])continue;
					q1.push(Dat(xx,yy));
					if(vis2[xx][yy]){
						//printf("--%d %d %d\n",cnt,xx,yy);
						printf("%d\n",cnt);
						return ;
					}
					vis1[xx][yy]=1;
					r1++;
				}
			}
		}	
		lst=r2;wtf=1;
		while(l2<=lst){
			x=q2.front().x,y=q2.front().y;q2.pop();//printf("%d %d\n",l2,lst);
			l2++;
			if(!check(x,y))continue;			
			for(ri i=0;i<4;i++){
				xx=x+dx[i],yy=y+dy[i];
				if(!check(xx,yy)||vis2[xx][yy])continue;
				q2.push(Dat(xx,yy));//printf("2 %d %d\n",xx,yy);
				if(vis1[xx][yy]){
					printf("%d\n",cnt);
					return ;
				}
				vis2[xx][yy]=1;
				r2++;
			}
			//printf("*** %d %d %d\n",l2,r2,lst);
		}
		cnt++;
		dis=cnt*2;
	}
	puts("-1");
	return ;
}
int main(){
	read(T);
	while(T--){
		read(n),read(m);
		gx1=gy1=inf;
		for(ri i=1;i<=n;i++){
			scanf("%s",str+1);
			for(ri j=1;j<=m;j++){
				vis1[i][j]=0,vis2[i][j]=0;
				if(str[j]=='.')g[i][j]=0;
				else if(str[j]=='X')g[i][j]=1;
				else if(str[j]=='M'){
					g[i][j]=2;
					sx=i,sy=j;
				}
				else if(str[j]=='G'){
					g[i][j]=3;
					tx=i,ty=j;
				}
				else if(str[j]=='Z'){
					if(gx1==inf)gx1=i,gy1=j;
					else gx2=i,gy2=j;
				}
			}
		}
		//printf("%d %d %d %d %d %d %d %d\n",sx,sy,tx,ty,gx1,gy1,gx2,gy2);
		bfs();
	}
	return 0;
}
posted @ 2018-08-26 22:52  Rye_Catcher  阅读(380)  评论(0)    收藏  举报