题目连接: Nightmare Ⅱ

题目:

Last night, little erriyue had a horrible nightmare. He dreamed that he and his girl friend were trapped in a big maze separately. More terribly, there are two ghosts in the maze. They will kill the people. Now little erriyue wants to know if he could find his girl friend before the ghosts find them.
You may suppose that little erriyue and his girl friend can move in 4 directions. In each second, little erriyue can move 3 steps and his girl friend can move 1 step. The ghosts are evil, every second they will divide into several parts to occupy the grids within 2 steps to them until they occupy the whole maze. You can suppose that at every second the ghosts divide firstly then the little erriyue and his girl friend start to move, and if little erriyue or his girl friend arrive at a grid with a ghost, they will die.
Note: the new ghosts also can devide as the original ghost.

Input
The input starts with an integer T, means the number of test cases.
Each test case starts with a line contains two integers n and m, means the size of the maze. (1<n, m<800)
The next n lines describe the maze. Each line contains m characters. The characters may be:
‘.’ denotes an empty place, all can walk on.
‘X’ denotes a wall, only people can’t walk on.
‘M’ denotes little erriyue
‘G’ denotes the girl friend.
‘Z’ denotes the ghosts.
It is guaranteed that will contain exactly one letter M, one letter G and two letters Z.

Output
Output a single integer S in one line, denotes erriyue and his girlfriend will meet in the minimum time S if they can meet successfully, or output -1 denotes they failed to meet.

Sample Input
3
5 6
XXXXXX
XZ…ZX
XXXXXX
M.G…

5 6
XXXXXX
XZZ…X
XXXXXX
M…
…G…

10 10

…X…
…M.X…X.
X…
.X…X.X.X.
…X
…XX…X.
X…G…X
…ZX.X…
…Z…X…X

Sample Output
1
1
-1

解题思路:

这个题有些复杂, 起初一想 两个人和鬼都应该BFS跑, 不出所料吃了T.
但实际上, 需要BFS的只有两个人, 因为鬼是可以穿墙的, 哪里都能跑, 因此鬼就相当于每轮向外扩两圈. 这样的话我们就能略去鬼需要的两次BFS.
而在判断人是否能跑到某个点时, 我们只需要判断鬼在当前轮次i*2的步数下能否到达该点即可.

AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
char a[1000][1000]; int n, m, res;
bool vis[1000][1000][2]; //分别记录M和G是否到达过该位置
int gx[2], gy[2]; //存放两个鬼的初始位置坐标
int fx[][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
struct node {int x, y;
};
queue<node> q[2]; //M, G
bool judge(int dx, int dy) //判断M和G在该位置能否存在.
{if (dx<1 || dy<1 || dx>n || dy>m || a[dx][dy] == 'X') return 0;if (abs(dx - gx[0]) + abs(dy - gy[0]) <= 2 * res) return 0; //鬼1能否达到if (abs(dx - gx[1]) + abs(dy - gy[1]) <= 2 * res) return 0; //鬼2能否达到return 1;
}
bool bfs(int ind) //ind是为了判断是M还是G
{int t = q[ind].size(); //只跑当前轮次while (t--) {node op = q[ind].front(); q[ind].pop();if (!judge(op.x, op.y)) continue; //因为鬼先手, 所以上一轮能跑到的地方这一轮不一定能存活.for (int i = 0; i < 4; i++) {int dx = op.x + fx[i][0];int dy = op.y + fx[i][1];if (vis[dx][dy][ind] || !judge(dx, dy)) continue;if (vis[dx][dy][ind ^ 1]) return 1; //相遇vis[dx][dy][ind] = 1; q[ind].push({ dx, dy });}}return 0;
}
int fact()
{res = 0;while (!q[0].empty() && !q[1].empty()) { //如果M或者G有1个为空, 则无法相遇res++;int cou = 3; while (cou--) if (bfs(0)) return res;if (bfs(1)) return res;}return -1; //无法相遇返回-1
}
int main(void)
{int t; cin >> t;while (t--) {while (!q[0].empty()) q[0].pop(); while (!q[1].empty()) q[1].pop(); memset(vis, 0, sizeof(vis));scanf("%d %d", &n, &m); int gin = 0;for (int i = 1; i <= n; i++) {scanf("%s", (a[i] + 1));for (int j = 1; j <= m; j++) {if (a[i][j] == 'M') { q[0].push({ i, j }); vis[i][j][0] = 1; } //Mif (a[i][j] == 'G') { q[1].push({ i, j }); vis[i][j][1] = 1; } //Gif (a[i][j] == 'Z') { gx[gin] = i, gy[gin++] = j; }}}cout << fact() << endl;}return 0;
}

特别说明: 由于本题测试数据问题, 如果你读图采用%c的方式读, 可能会有问题. 在样例输入时, 第二个图和第三个图之间多了一空行是题目自带的, 因此有可能在提示我们, 一个个测试样例之间可能会含有不等量的回车, 因此请使用%s的方式读入.

END

Nightmare Ⅱ(BFS)相关推荐

  1. hdu - 1072 Nightmare(bfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=1072 遇到Bomb-Reset-Equipment的时候除了时间恢复之外,必须把这个点做标记不能再走,不然可能造 ...

  2. bottom sheets_Excel 2013中的SHEET和SHEETS函数

    bottom sheets I've been experimenting with the new SHEET and SHEETS functions in Excel 2013, to see ...

  3. HDU Problem - 3085 Nightmare Ⅱ(双向BFS)

    题目链接 Problem Description Last night, little erriyue had a horrible nightmare. He dreamed that he and ...

  4. G - Nightmare Ⅱ (双向BFS)

    题目链接:SDTBU-ACM集训队暑期集训---第一讲 - Virtual Judge Last night, little erriyue had a horrible nightmare. He ...

  5. 专题训练二 搜索进阶 HDU - 3085 Nightmare Ⅱ (双向BFS + 曼哈顿距离)

    HDU - 3085 Nightmare Ⅱ (双向BFS + 曼哈顿距离) Problem Description Last night, little erriyue had a horrible ...

  6. HDU 3085 Nightmare Ⅱ【BFS +曼哈顿距离+综合性较强】

    Nightmare Ⅱ Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total S ...

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

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

  8. Nightmare Ⅱ(双向BFS)

    Nightmare Ⅱ 简直就是晕,都怪我太菜了 #include <iostream> #include <cstring> #include <cstdio> ...

  9. BFS——1072 Nightmare

    1072 Nightmare 文章目录 1072 Nightmare 题意: 小明被困在一个迷宫如下中: 1.小明每次可以花一个单位时间往上下左右的某个方向移动一格. 2.小明身上有一个炸弹,在第6个 ...

最新文章

  1. 基于相关滤波器的追踪(Correlation Filter-based Tracking)原理
  2. python 新建文件 hdfs_大数据学习(六):Python操作hdfs(包括追加数据文件到hdfs文件)...
  3. [转载]线上应用故障排查之一:高CPU占用
  4. linux小米随身wifi驱动下载,小米随身wifi驱动官方下载
  5. Dart核心语言基础const关键字与final关键字的区别
  6. pythonseleniumide使用_selenium第二课(脚本录制seleniumIDE的使用)
  7. 单片机中去耦电容的使用
  8. Android 隐藏类的使用
  9. 计算机cnc编程入门,数控车床编程入门自学方法与步骤,内容详细,值得一看!...
  10. python代码提取图片文字
  11. MobileNet_v1:深度可分离卷积
  12. 【计算机二级】综合题目
  13. 斐波纳契数列 python123
  14. 无线覆盖商场微信吸粉解决方案
  15. Axure 如何在页面加载时,设置文本框的内容为当前日期
  16. Qt Creator编写C++中文乱码解决方法
  17. 吉尔布雷斯的动作研究—《可以量化的管理学》
  18. 【日常实用】git的简单使用
  19. 机器学习-KNN算法
  20. fluent p1模型_Fluent辐射传热模型理论以及相关设置(一)

热门文章

  1. k折交叉验证优缺点_k折交叉验证(R语言)
  2. 医院his系统服务器需要配置,创智和宇 His医院系统单机(有备份数据库)配置...
  3. request:fail -202:net::ERR_CERT_AUTHORI
  4. Vue 使用echarts 地图自定义图标和修改图标样式,点击切换图标
  5. 删除360天擎(企业版)---不知道密码情况下
  6. 全网最细海龟 (turtle) 画图讲解 (五):输入/输出文字及鼠标与键盘交互设计
  7. 基于FFMPEG水印添加---avfilter库
  8. 点击a标签弹出iframe_iframe标签与a标签
  9. epub 免费转换网站
  10. centos7常用命令详解