[HDU3085] Nightmare Ⅱ 题解

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.

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,鬼的分裂可以用‘当前时间乘以2‘与‘人和鬼之间的曼哈顿距离‘来判断,当发现某个点被两个人都走过时即找到了最短相遇点,输出即可

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <bitset>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define rg register
#define LL long long
#define __space putchar(' ')
#define __endl putchar('\n')
template <typename qwq> inline void read(qwq & x)
{
    x = 0;
    rg int f = 1;
    rg char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    x *= f;
}
template <typename qaq> inline void print(qaq x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
int dx[] = {0,0,0,1,-1};
int dy[] = {0,1,-1,0,0};
char Map[805][805];
int t,n,m;
bool bvis[805][805],gvis[805][805];
struct node
{
    int x,y;
}boy,girl,zom1,zom2;
queue<node> b,g;
inline void prework()//输入,重置,找到男孩女孩和鬼
{
    rg bool flag = false;
    for (rg int i = 1;i <= n;++i) scanf("%s",Map[i] + 1);
    for (rg int i = 1;i <= n;++i)
    {
        for (rg int j = 1;j <= m;++j)
        {
            bvis[i][j] = gvis[i][j] = false;
            if (Map[i][j] == 'M') boy.x = i,boy.y = j;
            if (Map[i][j] == 'G') girl.x = i,girl.y = j;
            if (Map[i][j] == 'Z' && !flag) zom1.x = i,zom1.y = j,flag = true;
            if (Map[i][j] == 'Z' && flag) zom2.x = i,zom2.y = j;
        }
    }
    while (!b.empty()) b.pop();
    while (!g.empty()) g.pop();
}
inline bool judge(int x,int y)//边界判断
{
    if (x < 1 || x > n || y < 1 || y > m) return false;
    if (Map[x][y] == 'X') return false;
    return true;
}
inline bool Manhattan (int x,int y,int tm)//曼哈顿距离判断
{
    if (abs(x - zom1.x) + abs(y - zom1.y) <= 2 * tm) return false;
    if (abs(x - zom2.x) + abs(y - zom2.y) <= 2 * tm) return false;
    return true;
}
inline bool boy_friend_search()
{
    rg int tm = 0,size;
    b.push(boy),g.push(girl);
//  bvis[boy.x][boy.y] = gvis[girl.x][girl.y] = true;
    while (!b.empty() || !g.empty())
    {
        ++tm;
        rg int ntm = 3;
        while (ntm--)//男孩走3步
        {
            size = b.size();
            while (size--)
            {
                rg node nb = b.front();
                b.pop();
                rg int bx = nb.x,by = nb.y;
                if (!Manhattan(bx,by,tm)) continue;//鬼比人先走,所以要先判断是否撞鬼!
                for (rg int i = 1;i <= 4;++i)
                {
                    rg int nx = bx + dx[i];
                    rg int ny = by + dy[i];
                    if (!judge(nx,ny)) continue;
                    if (!Manhattan(nx,ny,tm)) continue;
                    if (bvis[nx][ny]) continue;//走过了就不要走了,不然MLE(别问我怎么知道的
                    bvis[nx][ny] = true;
                    if (gvis[nx][ny])
                    {
                        print(tm);
                        return true;
                    }
                    b.push((node) {nx,ny});
                }
            }
        }
        size = g.size();
        while (size--)//女孩走一步,同上
        {
            rg node ng = g.front();
            g.pop();
            rg int gx = ng.x,gy = ng.y;
            if (!Manhattan(gx,gy,tm)) continue;
            for (rg int i = 1;i <= 4;++i)
            {
                rg int nx = gx + dx[i];
                rg int ny = gy + dy[i];
                if (!judge(nx,ny)) continue;
                if (!Manhattan(nx,ny,tm)) continue;
                if (gvis[nx][ny]) continue;
                gvis[nx][ny] = true;
                if (bvis[nx][ny])
                {
                    print(tm);
                    return true;
                }
                g.push((node) {nx,ny});
            }
        }
    }
    return false;
}
int main()
{
    read(t);
    while (t--)
    {
        read(n),read(m);
        prework();
        if (!boy_friend_search()) print(-1);
        __endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Here-is-SG/p/10532953.html

时间: 2024-10-11 17:43:56

[HDU3085] Nightmare Ⅱ 题解的相关文章

HDU3085 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

HDU3085 Nightmare Ⅱ (双向BFS)

联赛前该练什么?DP,树型,状压当然是爆搜啦 双向BFS就是两个普通BFS通过一拼接函数联系,多多判断啦 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define R(a,b,c) for(register int a = (b); a <= (c); ++a) #define nR(a,b,c

HDU1072 Nightmare 【BFS】

Nightmare Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7367    Accepted Submission(s): 3530 Problem Description Ignatius had a nightmare last night. He found himself in a labyrinth with a ti

HDU 3085 - Nightmare Ⅱ - []

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 Problem DescriptionLast 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.

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

(leetcode题解)Pascal&#39;s Triangle

Pascal's Triangle  Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题意实现一个杨辉三角. 这道题只要注意了边界条件应该很好实现出来,C++实现如下 vector<vector<int>> generate(int

2017ZZUACM省赛选拔试题部分题解----谨以纪念我这卡线滚粗的美好经历

写在前面: 其实心里有些小小的不爽又有点小小的舒畅,为啥捏?不爽当然是因为没被选拔上啦,舒畅捏则是因为没被选拔上反而让自己警醒,学长也提点很多很多."沉下去,然后一战成名"学长如是对我说,我很开心.其实这完全算不算是题解,只是我个人的一些小想法而已.而且到现在还有一题不会...让自己长点记性吧. 题目 A :聪明的田鼠 Time Limit: 1 Sec Memory Limit: 128 MB Description 田鼠MIUMIU来到了一片农田,农田可以看成是一个M*N个方格的矩