[kuangbin]专题二 搜索进阶 Nightmare Ⅱ HDU - 3085【BFS】

【题目描述】
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可以移动3步,他的女朋友可以移动1步。鬼魂是邪恶的,每一秒他们就会分成几个部分,在两步之内占据网格,直到它们占据整个迷宫。你可以假设每一秒鬼先分裂然后小erriyue和他女朋友开始移动,如果小erriyue或者他女朋友到达鬼占领的区域,他们会死掉。
注意,新的鬼也会和原始鬼一样分裂。

【输入】
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个字符,字符可能是:
‘.’表示一个空的位置,都可以走过这里
‘X’表示墙,只有人不能经过
‘M’表示小erriyue
‘G’表示他女朋友
‘Z’表示鬼

【输出】
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.
输出一个整数一行,如果他们成功相遇表示他们最小的遇见时间,或者输出-1表示他们不能相遇。

【样例输入】

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

【样例输出】
1
1
-1

题目链接:https://cn.vjudge.net/problem/HDU-3085

分别对两个人进行BFS,中间判断会不会被鬼抓到,记录每个人到达某个位置的最短时间,最后取两者最大值的最小值即可
每秒erriyue走3步,他女朋友走1步,鬼走2步能穿墙能分身,比人先走,算曼哈顿距离判断能否到达某位置即可

代码如下:

#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
static const int MAXN=800;
static const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
char mp[MAXN+10][MAXN+10];
struct Ghost{
    int x,y;
}G1,G2;
struct Node{
    int x,y;
    int step;
};
int T,n,m;
int erriyue_vis[MAXN+10][MAXN+10];
int girlfriend_vis[MAXN+10][MAXN+10];
void erriyue_bfs(Node node)
{
    queue<Node> Q;
    Q.push(node);
    if(abs(G1.x-node.x)+abs(G1.y-node.y)>2)
        erriyue_vis[node.x][node.y]=0;
    else
        return;
    while(!Q.empty())
    {
        Node now=Q.front();
        Q.pop();
        for(int i=0;i<4;i++)
        {
            Node next;
            next.x=now.x+dx[i];
            next.y=now.y+dy[i];
            next.step=now.step+1;
            if(1<=next.x && next.x<=n && 1<=next.y && next.y<=m && mp[next.x][next.y]!='X' && erriyue_vis[next.x][next.y]==INF && ((next.step-1)/3+1)*2<abs(G1.x-now.x)+abs(G1.y-now.y) && ((next.step-1)/3+1)*2<abs(G2.x-now.x)+abs(G2.y-now.y) && ((next.step-1)/3+1)*2<abs(G1.x-next.x)+abs(G1.y-next.y) && ((next.step-1)/3+1)*2<abs(G2.x-next.x)+abs(G2.y-next.y))
            {
                erriyue_vis[next.x][next.y]=next.step;
                Q.push(next);
            }
        }
    }
}
void girlfriend_bfs(Node node)
{
    queue<Node> Q;
    Q.push(node);
    if(abs(G1.x-node.x)+abs(G1.y-node.y)>2)
        girlfriend_vis[node.x][node.y]=0;
    else
        return;
    while(!Q.empty())
    {
        Node now=Q.front();
        Q.pop();
        for(int i=0;i<4;i++)
        {
            Node next;
            next.x=now.x+dx[i];
            next.y=now.y+dy[i];
            next.step=now.step+1;
            if(1<=next.x && next.x<=n && 1<=next.y && next.y<=m && mp[next.x][next.y]!='X' && girlfriend_vis[next.x][next.y]==INF && next.step*2<abs(G1.x-now.x)+abs(G1.y-now.y) && next.step*2<abs(G2.x-now.x)+abs(G2.y-now.y) && next.step*2<abs(G1.x-next.x)+abs(G1.y-next.y) && next.step*2<abs(G2.x-next.x)+abs(G2.y-next.y))
            {
                girlfriend_vis[next.x][next.y]=next.step;
                Q.push(next);
            }
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--)
    {
        G1.x=G1.y=G2.x=G2.y=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>mp[i][j];
                if(mp[i][j]=='Z')
                    if(G1.x)
                        G2.x=i,G2.y=j;
                    else
                        G1.x=i,G1.y=j;                    
            }
        memset(erriyue_vis,0x3f,sizeof(erriyue_vis));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='M')
                    erriyue_bfs(Node{i,j,0});
        memset(girlfriend_vis,0x3f,sizeof(girlfriend_vis));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='G')
                    girlfriend_bfs(Node{i,j,0});
        int minstep=INF;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(erriyue_vis[i][j]!=INF)
                    minstep=min(minstep,max((erriyue_vis[i][j]-1)/3+1,girlfriend_vis[i][j]));
            }
        if(minstep==INF)
            cout<<-1<<endl;
        else
            cout<<minstep<<endl;
    }
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值