【Ybtoj 第5章 例题6】逃离噩梦【广搜】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路

鬼的覆盖范围不需要特别处理,只需要O(1)判断一下走没走到鬼的覆盖范围

接下来就是boy & girl了,
每秒boy走三步,girl走一步就很迷: )
他俩必须同时BFS,但是是两个不同的队列
那么boy直接就加一层循环寻三步就ok了
boy & girl走到的点分别开数组标记,当两个数组在每个位置上都被标记了,就代表他们会和了,输出当时用的时间。


代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <cmath>
using namespace std;

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

bool ok=0;
int T,n,m,a[810][810],kj[3][3],f1[1000000][3],f2[1000000][3],v1[810][810],v2[810][810];
char c;

bool check1(int x,int y,int s) {
	if(x>0&&y>0&&x<=n&&y<=m&&a[x][y]!=1&&a[x][y]!=-1) {
		int lyx1=abs(kj[1][1]-x)+abs(kj[1][2]-y),lyx2=abs(kj[2][1]-x)+abs(kj[2][2]-y);
		if(lyx1>s*2&&lyx2>s*2)
			return 1;
		else
			return 0;
	} else return 0;
}

bool check2(int x,int y,int s) {
	if(x>0&&y>0&&x<=n&&y<=m&&a[x][y]!=1&&a[x][y]!=-1) {
		int lyx1=abs(kj[1][1]-x)+abs(kj[1][2]-y),lyx2=abs(kj[2][1]-x)+abs(kj[2][2]-y);
		         if(lyx1>s*2&&lyx2>s*2)
			         return 1;
		else
			return 0;
	} else return 0;
}

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;
}

void bfs() {
	int h1=0,t1=1,h2=0,t2=1,s1=0,e1=1,s2=0,e2=1;
	for(int s=1; h1!=t1||h2!=t2; s++) {
		for(int i=1; i<=3; i++) {
			for(int j=abs(s1-e1); j>0; j--) {
				h1=(h1%999999)+1,s1++;
				for(int ii=1; ii<=4; ii++) {
					int xx=f1[h1][1]+dx[ii],yy=f1[h1][2]+dy[ii];
					if(check1(xx,yy,s)&&!v1[xx][yy]&&check1(f1[h1][1],f1[h1][2],s)) {
						t1=(t1%999999)+1,e1++;
						f1[t1][1]=xx,f1[t1][2]=yy;
						v1[xx][yy]=1;
						if(v2[xx][yy]==1) {
							printf("%d\n",s);
							return ;
						}
					}
				}

			}
		}
		for(int j=abs(s2-e2); j>0; j--) {
			h2=(h2%999999)+1,s2++;
			for(int ii=1; ii<=4; ii++) {
				int xx=f2[h2][1]+dx[ii],yy=f2[h2][2]+dy[ii];
				if(check2(xx,yy,s)&&!v2[xx][yy]&&check2(f2[h2][1],f2[h2][2],s)) {
					t2=(t2%999999)+1,e2++;
					f2[t2][1]=xx,f2[t2][2]=yy;
					v2[xx][yy]=1;
					if(v1[xx][yy]==1) {
						printf("%d\n",s);
						return ;
					}
				}
			}

		}
	}
	cout<<-1<<endl;
	return;
}

int main() {
	T=read();
	while(T--) {
		memset(v1,0,sizeof(v1));
		memset(v2,0,sizeof(v2));
		memset(a,0,sizeof(a));
		scanf("%d%d",&n,&m);
		ok=0;
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=m; j++) {
				cin>>c;
				if(c=='X') a[i][j]=1;
				if(c=='Z'&&!ok)
					kj[1][1]=i,kj[1][2]=j,a[i][j]=-1,ok=1;
				if(c=='Z'&&ok==1)
					kj[2][1]=i,kj[2][2]=j,a[i][j]=-1;
				if(c=='M')
					f1[1][1]=i,f1[1][2]=j,v1[i][j]=1;
				if(c=='G')
					f2[1][1]=i,f2[1][2]=j,v2[i][j]=1;
			}
		}
		bfs();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值