HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ)

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,表示迷宫大小。(1<n, m<800)
随后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在单独一行;否则输出-1
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++

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <queue>
 5 #define MX 805
 6 #define INF 0x7F7F7F7F
 7 struct Point {
 8     int y, x;
 9 }M, G, Z[2], now, nxt;
10 int data[MX][MX][2], drc[8] = { -1, 0, 1, 0, 0, -1, 0, 1 };
11 bool isCatch(int y, int x, int tim) {
12     return std::min(abs(y - Z[0].y) + abs(x - Z[0].x), abs(y - Z[1].y) + abs(x - Z[1].x)) <= tim * 2;
13 }
14 void BFS() {
15     int i = 0, j, tim, tmp;
16     std::queue<Point> q;
17     for (i = 0; i < 2; ++i) {
18         i ? q.push(G) : q.push(M);
19         while (!q.empty()) {
20             now = q.front(); q.pop();
21             tim = data[now.y][now.x][i] + 1;
22             tmp = i ? tim : (tim + 2) / 3;
23             if (isCatch(now.y, now.x, tmp)) continue;
24             for (j = 0; j < 8; j += 2) {
25                 nxt.y = now.y + drc[j]; nxt.x = now.x + drc[j + 1];
26                 if (isCatch(nxt.y, nxt.x, tmp) || data[nxt.y][nxt.x][i] <= tim) continue;
27                 data[nxt.y][nxt.x][i] = tim;
28                 q.push(nxt);
29             }
30         }
31     }
32 }
33 int main() {
34     char str[MX];
35     int t, i, j, n, m, iz, opt, tim;
36     scanf("%d", &t);
37     while (t--) {
38         scanf("%d%d ", &n, &m);
39         memset(data, -1, sizeof data); iz = 0;
40         for (i = 0; i < n; ++i) {
41             gets(str);
42             for (j = 0; j < m; ++j) {
43                 switch (str[j]) {
44                     case '.': data[i + 1][j + 1][0] = data[i + 1][j + 1][1] = INF; break;
45                     case 'Z': Z[iz].y = i + 1; Z[iz].x = j + 1; ++iz; break;
46                     case 'M': M.y = i + 1; M.x = j + 1; break;
47                     case 'G': G.y = i + 1; G.x = j + 1; break;
48                 }
49             }
50         }
51         data[M.y][M.x][1] = data[G.y][G.x][0] = INF;
52         data[M.y][M.x][0] = data[G.y][G.x][1] = 0;
53         BFS();
54         opt = INF;
55         for (i = 1; i <= n; ++i) {
56             for (j = 1; j <= m; ++j) {
57                 if ((data[i][j][0] | data[i][j][1]) == -1) continue;
58                 tim = std::max((data[i][j][0] + 2) / 3, data[i][j][1]);
59                 opt = std::min(opt, tim);
60             }
61         }
62         opt > MX ? puts("-1") : printf("%d\n", opt);
63     }
64     return 0;
65 }
posted @ 2017-06-15 15:20  Simon_X  阅读(291)  评论(0编辑  收藏  举报