题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085

题目大意:给你一张n*m地图上,上面有有

  ‘. ’:路

  ‘X':墙

  ’Z':鬼,每秒移动2步,可以穿墙,开始有两个,每开始时鬼先动。

  ‘M’:男生,每秒可走3步。

  ‘G’:女生,每秒可走1步。

解题思路:第一次写双向BFS,写了我好久,开始还是想着先bfs计算step[x][y][t]把每个位置被鬼占据的时间处理一下然后再用双向BFS计算两人相遇时间。后来发现因为鬼可以穿墙,可以直接用曼哈顿距离判断是否会被鬼抓到。还有,开始我都不知道每秒走三步怎么搞。。。后来看了网上的博客,知道可以通用size限制一下出队数,三次bfs实现每秒走三步。太乱了,稍微总结一下:

     ①两人给vis[x][y]分别标记1,2当某次bfs遇到不同标记说明两人相遇。

     ②用曼哈顿距离判断时间t走到某个位置是否会被鬼抓到。

     ③因为鬼先行动,每次t+1时,在人行动前要判断在当前位置会不会被鬼抓到。

     ④用size=q[mark].size()控制每次出队数,实现一秒走三步。

     ⑤最坑爹的一点,用scanf("%c",&map[i][j])无限超时,感觉里面绝对有不正常的数据,后来用scanf("%s",map[i]+1)每次输入一行才过掉。

代码:

 #include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=; int n,m,t;
int d[][]={{-,},{,},{,-},{,}};
char map[N][N];
int vis[N][N]; struct node{
int x,y;
}M,G,pre,now,a[];
queue<node>q[]; bool judge(int x,int y){
if(x<||y<||x>n||y>m||map[x][y]=='X')
return false;
//利用曼哈顿距离判断是否会被鬼抓到
for(int i=;i<=;i++){
if(abs(x-a[i].x)+abs(y-a[i].y)<=*t)
return false;
}
return true;
} bool bfs(int mark){
//小技巧,利用size就可以控制出队的都是上一步的,而不会将这一步的也出队,就能实现走3步了。
int size=q[mark].size();
while(size--){
pre=q[mark].front();
q[mark].pop();
//鬼在人之前行动,时间每增加1,先判断鬼能不能把人吃掉
if(!judge(pre.x,pre.y))
continue;
for(int i=;i<;i++){
int xx=pre.x+d[i][];
int yy=pre.y+d[i][];
if(!judge(xx,yy))
continue;
//遇到不同标记说明两人相遇
if(vis[xx][yy]){
if(vis[xx][yy]!=mark)
return true;
else
continue;
}
vis[xx][yy]=mark;
now.x=xx;
now.y=yy;
q[mark].push(now);
}
}
return false;
} int solve(){
//清空队列
while(!q[].empty()) q[].pop();
while(!q[].empty()) q[].pop();
q[].push(M);
q[].push(G);
vis[M.x][M.y]=,vis[G.x][G.y]=;
t=;
//双向bfs
while(!q[].empty()||!q[].empty()){
t++;
for(int i=;i<=;i++){
if(bfs())
return t;
}
if(bfs())
return t;
}
return -;
} int main(){
int T;
scanf("%d",&T);
while(T--){
memset(vis,,sizeof(vis));
scanf("%d%d",&n,&m);
//注意用scanf("%c",map[i][j])会超时
for(int i=,cnt=;i<=n;i++){
scanf("%s",map[i]+);
for(int j=;j<=m;j++){
if(map[i][j]=='M')
M.x=i,M.y=j;
if(map[i][j]=='G')
G.x=i,G.y=j;
if(map[i][j]=='Z')
a[++cnt].x=i,a[cnt].y=j;
}
}
printf("%d\n",solve());
}
return ;
}

HDU 3085 Nightmare Ⅱ(双向BFS)的更多相关文章

  1. HDU 3085 Nightmare Ⅱ (双向BFS)

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

  2. HDU 3085 Nightmare Ⅱ 双向BFS

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

  3. Nightmare Ⅱ HDU - 3085 (双向bfs)

    Last night, little erriyue had a horrible nightmare. He dreamed that he and his girl friend were tra ...

  4. HDU - 3085 Nightmare Ⅱ

    HDU - 3085 Nightmare Ⅱ 双向BFS,建立两个队列,让男孩女孩一起走 鬼的位置用曼哈顿距离判断一下,如果该位置与鬼的曼哈顿距离小于等于当前轮数的两倍,则已经被鬼覆盖 #includ ...

  5. HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ)

    HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Ja ...

  6. HDU 3085 Nightmare II 双向bfs 难度:2

    http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...

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

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

  8. 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...

  9. HDU 1242 -Rescue (双向BFS)&amp;&amp;( BFS+优先队列)

    题目链接:Rescue 进度落下的太多了,哎╮(╯▽╰)╭,渣渣我总是埋怨进度比别人慢...为什么不试着改变一下捏.... 開始以为是水题,想敲一下练手的,后来发现并非一个简单的搜索题,BFS做肯定出 ...

随机推荐

  1. elasticsearch 第五篇(文档操作接口)

    INDEX API 示例: 1 2 3 4 5 PUT /test/user/1 { "name": "silence", "age": 2 ...

  2. 解题:BZOJ 4808 马

    题面 以前写过的题,翻出来学习网络流写二分图匹配,因为复杂度更优秀,$Dinic$是$O(sqrt(n)m)$哒~ 原点向左部点连流量为$1$的边,左部点向对应右部点连流量为$1$的边,右部点向汇点连 ...

  3. python基础----数据类型二

    数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定 ...

  4. 小程序navigatorTo缺点和修正方法

    1.不好带参数跳转到tabbar,即下部的导航栏目. reLauntch方法可以传递参数到导航栏目: go_to_prolist: function (e) { var datatype = e.cu ...

  5. springsecurity remember-me 功能

    本文基于spring-security-web-4.1.2.RELEASE. 要实现rememberMe,有两种方案. 1.基于简单加密token的方法 首先需要在配置文件中加入<remembe ...

  6. windows安装zookeeper和kafka,flume

    一.安装JDK 过程比较简单,这里不做说明. 最后打开cmd输入如下内容,表示安装成功 二.安装zooeleeper 下载安装包:http://zookeeper.apache.org/release ...

  7. 游戏AI:行为树

    Behavior Tree 行为树通过子Task的返回值决定整棵树的走向 Task 行为树上的每个节点都称为一个Task, 每个Task存在三种状态, success, failure, runnin ...

  8. [oracle]centos 7 安装oracle

    换了好几个系统终于还是利用centos安装oralce成功了,这里我也参考了网上的好多资料以及oracle的官方文档 1.下载oracle,我这里选择的是11gr2版本,下载下来后有两个文件,利用un ...

  9. 2016-2017-2 20155117实验二《Java面向对象程序设计》实验报告

    实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验要求 1.参考Intellj IDEA 简易教程 提交 ...

  10. 【洛谷 P3299】 [SDOI2013]保护出题人 (凸包,三分,斜率优化)

    题目链接 易得第\(i\)关的最小攻击力为\(\max_{j=1}^i\frac{sum[i]-sum[j-1]}{x+d*(i-j)}\) 十分像一个斜率式,于是看作一个点\(P(x+d*i,sum ...