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;
}
HDU3085NightmareII题解--双向BFS的更多相关文章
- HDU3085(双向BFS+曼哈顿距离)题解
Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 6171 Admiral(双向BFS+队列)题解
思路: 最大步骤有20,直接BFS会超时. 因为知道开始情况和结果所以可以用双向BFS,每个BFS规定最大步骤为10,这样相加肯定小于20.这里要保存每个状态搜索到的最小步骤,用Hash储存.当发现现 ...
- [题解](双向bfs)hdu_3085_Nightmare Ⅱ
发现直接搜索比较麻烦,但是要同时两个人一起走容易想到双向bfs,比较普通, 在判断是否碰到ghost时只要比较两点的曼哈顿距离大小和step*2(即ghost扩散的距离)即可,仔细思考也是可以想到的 ...
- HDU 3085 Nightmare Ⅱ 双向BFS
题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...
- UVA1601-The Morning after Halloween(双向BFS)
Problem UVA1601-The Morning after Halloween Accept: 289 Submit: 3136 Time Limit: 12000 mSec Problem ...
- 【bzoj5049】[Lydsy九月月赛]导航系统 并查集+双向BFS最短路
题目描述 给你一张 $n$ 个点 $m$ 条边的随机图,边权为1.$k$ 次询问两点间最短路,不连通则输出-1. 输入 第一行包含3个正整数n,m,k(2<=n<=100000,1< ...
- HDU——1195Open the Lock(双向BFS)
Open the Lock Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- HDU3085 Nightmare Ⅱ —— 双向BFS + 曼哈顿距离
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Other ...
- 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.2 位于Shell脚本第一行的#!
学习<shell脚本学习指南>一书,记录总结,便于自己回忆,希望对你有帮助! 2.4 自给自足的脚本:位于第一行的 #! 1.Shell脚本执行过程 当Shell执行一个程序时,会要求UN ...
- vsCode安装todo插件
使用过IDEA或者WebStrom的阿媛应该都知道他们都有一个TODO功能,方便我们跟踪注释,或者说是我们在项目代码里面所做的标记:但是如果你现在在使用vsCode,你会发现,没有TODO功能,幸好, ...
- shiro中接入单点登录功能
最近新建的系统中使用了shiro,而shiro框架中包含登录认证和鉴权的功能,因为我们系统要统一接入公司内部的单点登录(isso)系统,所以通过isso的登录用户,需要在shiro中置为已认证,一下提 ...
- php如何开启gd2扩展
extension=php_gd2.dll 找到php的配置文件php.ini,搜索extension=php_gd2.dll,去掉前面的分号即可:如果没有直接添加这种情况适合于windows系统和编 ...
- c++ STL之unordered_map
1.1 特性 关联性:通过key去检索value,而不是通过绝对地址(和顺序容器不同) 无序性:使用hash表存储,内部无序 Map : 每个值对应一个键值 键唯一性:不存在两个元素的键一样 动态内存 ...
- python 实例方法、类方法和静态方法
#!/usr/bin/env python3.6 #-*- coding:utf-8 -*- # class Person(object): city = 'Beijing' def __init__ ...
- 前端构建工具gulp使用 (转)
http://www.cnblogs.com/starof/p/5194622.html 前端自动化流程工具,用来合并文件,压缩等. Gulp官网 http://gulpjs.com/ Gulp中文网 ...
- 转载:深入理解Spring MVC 思想
原文作者:赵磊 原文地址:http://elf8848.iteye.com/blog/875830 目录 一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.sp ...
- vue中如何使用event对象
原文地址 一.event 对象 (一)事件的 event 对象 你说你是搞前端的,那么你肯定就知道事件,知道事件,你就肯定知道 event 对象吧?各种的库.框架多少都有针对 event 对象的处理. ...
- 《JAVA语言》第三节课
使用递归方式判断某个字串是否是回文( palindrome ). 1. 设计思想 在判断字符串是否是回文的时,采用递归法,首先要分析出重复做的是什么事情,这里是要重复判断两端的字符是不是相等的,直到剩 ...