题目链接: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. POJ P3254 Corn fields 【状压dp】

    Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16909 Accepted: 8939 Descript ...

  2. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  3. 安装lighttpd

    依赖包: zlib,pcre,cronolog,bzip2, 1: 将lighttpd的原码包.以土豆现用lighttpd配置文件为基础的lighttpd.conf文件.日志轮循工具cronolog  ...

  4. 常用Actoin算子 与 内存管理 、共享变量、内存机制

    一.常用Actoin算子 (reduce .collect .count .take .saveAsTextFile . countByKey .foreach ) collect:从集群中将所有的计 ...

  5. AtCoder Regular Contest 088 E - Papple Sort(树状数组+结论)

    结论:每次把字符丢到最外面最优,用树状数组统计答案,把字符放到最外边后可以当成消失了,直接在树状数组上删掉就好. 感性理解是把字符丢到中间会增加其他字符的移动次数,但是丢到外面不会,所以是正确的. # ...

  6. 【树状数组】【P3902】 递增

    传送门 Description 给你一个长度为\(n\)的整数数列,要求修改最少的数字使得数列单调递增 Input 第一行为\(n\) 第二行\(n\)个数代表数列 Output 输出一行代表答案 H ...

  7. 《剑指offer》— JavaScript(7)斐波那契数列

    斐波那契数列 题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项. n<=39 实现代码 function Fibonacci(n) { var arr = ...

  8. Codeforces 526.D Om Nom and Necklace

    D. Om Nom and Necklace time limit per test 1 second memory limit per test 256 megabytes input standa ...

  9. POJ2234:Matches Game(Nim博弈)

    Matches Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12325   Accepted: 7184 题目链 ...

  10. bzoj 2795 [Poi2012]A Horrible Poem hash+数论

    2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 640  Solved: 322[Subm ...