题目链接

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

HDU3085NightmareII题解--双向BFS的更多相关文章

  1. HDU3085(双向BFS+曼哈顿距离)题解

    Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  2. HDU 6171 Admiral(双向BFS+队列)题解

    思路: 最大步骤有20,直接BFS会超时. 因为知道开始情况和结果所以可以用双向BFS,每个BFS规定最大步骤为10,这样相加肯定小于20.这里要保存每个状态搜索到的最小步骤,用Hash储存.当发现现 ...

  3. [题解](双向bfs)hdu_3085_Nightmare Ⅱ

    发现直接搜索比较麻烦,但是要同时两个人一起走容易想到双向bfs,比较普通, 在判断是否碰到ghost时只要比较两点的曼哈顿距离大小和step*2(即ghost扩散的距离)即可,仔细思考也是可以想到的 ...

  4. HDU 3085 Nightmare Ⅱ 双向BFS

    题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...

  5. UVA1601-The Morning after Halloween(双向BFS)

    Problem UVA1601-The Morning after Halloween Accept: 289 Submit: 3136 Time Limit: 12000 mSec  Problem ...

  6. 【bzoj5049】[Lydsy九月月赛]导航系统 并查集+双向BFS最短路

    题目描述 给你一张 $n$ 个点 $m$ 条边的随机图,边权为1.$k$ 次询问两点间最短路,不连通则输出-1. 输入 第一行包含3个正整数n,m,k(2<=n<=100000,1< ...

  7. HDU——1195Open the Lock(双向BFS)

    Open the Lock Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  8. HDU3085 Nightmare Ⅱ —— 双向BFS + 曼哈顿距离

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Other ...

  9. CSUOJ2031-Barareh on Fire(双向BFS)

    Barareh on Fire Submit Page Description The Barareh village is on fire due to the attack of the virt ...

随机推荐

  1. koa 项目实战(八)生成token

    1.安装模块 npm install jsonwebtoken --save 2.引用 const jwt = require('jsonwebtoken'); ... // 返回token cons ...

  2. DOS 获取硬盘序列号

    DOS命令行操作: 使用diskpart命令,Win+R键运行cmd,进入命令行界面:       1.diskpart       2.list disk 查看有几块硬盘       3.selec ...

  3. zabbix server端与agent端源码安装 自定义监控项

    ZabbixServer的安装(只有源码装zabbix才能装支持java) 搭建自定义yum仓库并安装支持包 yum -y install createrepo #下载依赖关系命令 createrep ...

  4. LC 971. Flip Binary Tree To Match Preorder Traversal

    Given a binary tree with N nodes, each node has a different value from {1, ..., N}. A node in this b ...

  5. 用JSON文本动态创建DataGrid

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  6. h5 与原生 app 交互的原理

    现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次就来捋 ...

  7. JVM学习笔记之认识JDK(一)

    1. HotSpot VM: HotSpot VM是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机. 什么是HotSpot VM & 深入理解Java虚拟机 ...

  8. 找不到FileProvider类怎么办?找不到R资源怎么办?APPT2错误怎么办?

    坑2: 在使用上述解决方案时,需要加入android.support.v4.content.FileProvider这个类,当时我没有这个包.但是在引入相应的依赖包后,各种异常就出现了. 先是把And ...

  9. 小D课堂 - 新版本微服务springcloud+Docker教程_3-06 服务注册和发现之Eureka Client搭建商品服务实战

    笔记 6.服务注册和发现之Eureka Client搭建商品服务实战     简介:搭建用商品服务,并将服务注册到注册中心 1.创建一个SpirngBoot应用,增加服务注册和发现依赖     2.模 ...

  10. ELK故障处理,不知道成功否

    上周?还是上上周??发现ELK的数据都没有更新了,考虑到这个系统目前不重要,就没有理会.今日再次登陆,发现没有数据更新了!!! system overview 没有主机,没有数据. 登陆系统检查状态, ...