HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ)

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

 

Problem Description - 题目描述

  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.
昨晚,erriyue经历了一场可怕的噩梦。他梦见自己和女朋友被困在一座大迷宫中。更糟的是,还有两杀人恶鬼环伺其中。现在erriyue想知道自己是否能先于恶鬼找到女朋友。
你可以认为erriyue和他女朋友可以移动4个方向。每回合,erriyue可以移动3步且他女朋友可以移动1步。恶鬼比较溜,可以随意分裂并不断占据2步内的格子,直到覆盖迷宫。每回合鬼先动,人再动,若走到有鬼的格子,卒。
注意:新旧鬼皆能分裂。

CN

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.

输入开头为整数T,表示测试用例数。
每组测试用例头一行有两个整数n和m,表示迷宫大小。(<n, m<)
随后n行迷宫。每行m个字符,表意如下:
‘.’ 空格,谁都能走。
‘X’ 墙,唯鬼能过。
‘M’ erriyue。
‘G’ 女朋友。
‘Z’ 恶鬼。
数据保证仅有一个M,一个G和两个Z。

CN

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.

如果erriyue 和女朋友可以在最短时间S成功相遇,则输出整数S在单独一行;否则输出-。

CN

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(当然双向也可以)

  人可以等人,人不能穿鬼,鬼比人快1s……

  然后把两层结果比较一下就行了。

代码 C++

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#define MX 805
#define INF 0x7F7F7F7F
struct Point {
int y, x;
}M, G, Z[], now, nxt;
int data[MX][MX][], drc[] = { -, , , , , -, , };
bool isCatch(int y, int x, int tim) {
return std::min(abs(y - Z[].y) + abs(x - Z[].x), abs(y - Z[].y) + abs(x - Z[].x)) <= tim * ;
}
void BFS() {
int i = , j, tim, tmp;
std::queue<Point> q;
for (i = ; i < ; ++i) {
i ? q.push(G) : q.push(M);
while (!q.empty()) {
now = q.front(); q.pop();
tim = data[now.y][now.x][i] + ;
tmp = i ? tim : (tim + ) / ;
if (isCatch(now.y, now.x, tmp)) continue;
for (j = ; j < ; j += ) {
nxt.y = now.y + drc[j]; nxt.x = now.x + drc[j + ];
if (isCatch(nxt.y, nxt.x, tmp) || data[nxt.y][nxt.x][i] <= tim) continue;
data[nxt.y][nxt.x][i] = tim;
q.push(nxt);
}
}
}
}
int main() {
char str[MX];
int t, i, j, n, m, iz, opt, tim;
scanf("%d", &t);
while (t--) {
scanf("%d%d ", &n, &m);
memset(data, -, sizeof data); iz = ;
for (i = ; i < n; ++i) {
gets(str);
for (j = ; j < m; ++j) {
switch (str[j]) {
case '.': data[i + ][j + ][] = data[i + ][j + ][] = INF; break;
case 'Z': Z[iz].y = i + ; Z[iz].x = j + ; ++iz; break;
case 'M': M.y = i + ; M.x = j + ; break;
case 'G': G.y = i + ; G.x = j + ; break;
}
}
}
data[M.y][M.x][] = data[G.y][G.x][] = INF;
data[M.y][M.x][] = data[G.y][G.x][] = ;
BFS();
opt = INF;
for (i = ; i <= n; ++i) {
for (j = ; j <= m; ++j) {
if ((data[i][j][] | data[i][j][]) == -) continue;
tim = std::max((data[i][j][] + ) / , data[i][j][]);
opt = std::min(opt, tim);
}
}
opt > MX ? puts("-1") : printf("%d\n", opt);
}
return ;
}

HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ)的更多相关文章

  1. HDU - 3085 Nightmare Ⅱ

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

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

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

  3. HDU 3085 Nightmare Ⅱ(双向BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 题目大意:给你一张n*m地图上,上面有有 ‘. ’:路 ‘X':墙 ’Z':鬼,每秒移动2步,可 ...

  4. HDU 3085 Nightmare Ⅱ (双向BFS)

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

  5. HDU 3085 Nightmare Ⅱ 双向BFS

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

  6. [hdu P3085] Nightmare Ⅱ

    [hdu P3085] Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...

  7. 【HDU 3085】 Nightmare Ⅱ

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3085 [算法] 双向BFS [代码] #include<bits/stdc++.h> ...

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

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

  9. 【HDU - 3085】Nightmare Ⅱ(bfs)

    -->Nightmare Ⅱ 原题太复杂,直接简单的讲中文吧 Descriptions: X表示墙 .表示路 M,G表示两个人 Z表示鬼 M要去找G但是有两个鬼(Z)会阻碍他们,每一轮都是M和G ...

随机推荐

  1. mybatis模糊查询

    今天遇到一个模糊查询的问题,需求是:根据传入的时间查询当天的所有数据,解决办法是使用$或者contact,具体sql模拟如下: select * from table_name where creat ...

  2. IIS宿主WCF服务*.svc Mime类型映射

    经常会遇到由于.net安装组件缺失,导致发布wcf服务后,访问wcf报.svc请求类型不支持 简单方法就是添加删除程序,修改.net组件安装选项,勾选http激活即可: 或者手工添加映射处理程序 1. ...

  3. VisualStudioCode创建的asp.net core项目部署到linux,使用nginx代理

    1.准备工作: a:使用VisualStudioCode创建asp.net core项目,并使用命令“dotnet publish”发布(可以参考前面两篇文章). 如:dotnet publish - ...

  4. opencart分类筛选逻辑修改为并且条件

    opencart分类筛选模式默认是或的逻辑,满足条件1或条件2都展现出来,如果想要改成既满足条件1又满足条件2要怎么改呢?有一个插件可以实现,FixFilter OC2x,可以修改默认的筛选条件 1. ...

  5. IP地址子网划分

    广播数据包: 要弄清为何需要划分子网,就需要了解网络传输过程中的广播概念. 经过多年的发展,交换机基本替代集线器,成为网络中主要的端终接入网络的基础设备,这也使得广播包发送数量有明显的减少,但交换机一 ...

  6. 快速排序 之添加复合插入排序和原始序列取中值左pivot

    quicksort中,当n小于一定值时,排序效率就比直接插入排序底了,所以,此时就不要再递归下去了,直接插入排序好了:快速的原理就是因为折半递归,所以初始pivot应该有个好一点的选择,这里在原序列左 ...

  7. RDD弹性分布式数据集的基本操作

    RDD的中文解释是弹性分布式数据集.构造的数据集的时候用的是List(链表)或者Array数组类型/* 使用makeRDD创建RDD */ /* List */ val rdd01 = sc.make ...

  8. CentOS7中PPTP的配置

    最近做各种vpn,记录一下pptp的流程 1.准备 #yum install -y perl ppp iptables //centos默认安装了iptables和ppp   2.安装pptpd #y ...

  9. 用AOP记录操作日志,并写进数据库。

    先用AOP注解 1 package com.vlandc.oss.apigate.log.aspect; import java.util.Map; import java.util.Optional ...

  10. C博客作业06--结构体&文件

    1.本章学习总结 1.1思维导图 1.2本章学习体会 学习了结构和文件,又是懵懵的课了,我的天啊.结构还好,题目集一出就做了,不是很难,感觉掌握的还可以,不过这只是感觉而已,等到真正来写大作业的时候又 ...