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 ...
随机推荐
- spark MLlib的 pipeline方式
spark mllib的pipeline,是指将多个机器学习的算法串联到一个工作链中,依次执行各种算法. 在Pipeline中的每个算法被称为"PipelineStage",表示其 ...
- [java] 将整数在千分位或万分位以逗号分隔表示
简单使用DecimalFormat的功能就能做到了,代码如下: package com.testEmp; import java.text.DecimalFormat; public class Nu ...
- MySQL 的连接时长控制--interactive_timeout和wait_timeout
在用MySQL客户端对数据库进行操作时,如果一段时间没有操作,再次操作时,常常会报如下错误: ERROR 2013 (HY000): Lost connection to MySQL server d ...
- document.querySelectorAll遍历
document.querySelectorAll兼容性良好,在之前的项目中就其遍历方式出了错误,先做个小结: 1.for循环 传统遍历方法 for(var i= 0; i< document. ...
- MATLAB学习(二)读写xls文件
>> N=xlsread('DRINK.xls','DRINK','A1:D8') N = 207.2000 3.3000 15.5000 2.8000 36.8000 5.9000 12 ...
- nginx配置静态资源关闭访问日志
location ~ .*\.(css|js|gif|png|jpg|jpeg|bmp|swf)$ { root $root_path; access_log off; }
- Java集合(6):理解Map
映射表的基本思想是维护键-值对的关联,通过键来寻找值.下面是标准Java类库中几种Map的实现: (1) HashMap:Map基于散列表的实现,插入和查询键值对的开销是固定的.可以通过构造器设置容量 ...
- 【JVM学习笔记】Class.forName方法学习
三个参数的版本的源代码如下 doc文档翻译 使用给定的类加载器(即第3个参数)返回与具有给定字符串名称(第1个参数)的类或接口关联的Class对象.给定类或接口的完全限定名称(以getName返回的相 ...
- JavaScript(6)—— 返回特征数字
案例要求 根据业务情况,要把核心的东西变成一个模块便于复用,慢慢沉淀后,能够更快更高效地编程. 业务核心算法: /* 数字检测 @return 返回2,能被3和7整除 返回1,能够被3整除 返回0,不 ...
- springboot-helloworld-eclipse
1.eclipse安装springboot插件 2.new->Spring Start ->group:组名称:artifact:组件名称:->选中web->finish 3. ...