177. 噩梦( bfs)

题目链接:https://www.acwing.com/problem/content/179/
给定一张N*M的地图,地图中有1个男孩,1个女孩和2个鬼。

字符“.”表示道路,字符“X”表示墙,字符“M”表示男孩的位置,字符“G”表示女孩的位置,字符“Z”表示鬼的位置。

男孩每秒可以在道路上移动3个单位距离,女孩每秒可以在道路上移动1个单位距离。

每个鬼占据的区域每秒可以向四周扩张2个单位距离,并且无视墙的阻挡,也就是在第k秒后所有与鬼的曼哈顿距离不超过2k的位置都会被鬼占领。

求在不进入鬼的占领区的前提下,男孩和女孩能否会合,若能会合,求出最短会合时间。
输入格式

第一行包含整数T,表示共有T组测试用例。

每组测试用例第一行包含两个整数N和M,表示地图的尺寸。

接下来N行每行M个字符,用来描绘整张地图的状况。(注意:地图中一定有且仅有1个男孩,1个女孩和2个鬼)
输出格式

每个测试用例输出一个整数S,表示最短会合时间。

如果无法会合则输出-1。

每个结果占一行。
数据范围

1<n,m<800

输入样例:

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

分析:今夜是想哭的一天。
感觉回到了大一的bug时代。我也不知道为什么,但是它就是错了。我也很绝望。明明就是一样的,重敲一遍,怎么就过了呢。5555~~~
这个题,我们可以在bfs的时候,同时bfs男孩,女孩,和鬼。如果男孩和女孩能够同时相遇,那么就返回值。注意,男孩要bfs三次,女孩1次,鬼两次。
思路很简单。
我的wa点
1,char打成了int。自己这个智障玩意
2,bfs三次,直接把队头的值记录下来就好了,非要傻逼搞。
3,我爆队列了,明显标记打错了。可是我找不到 555

#include"stdio.h"
#include"string.h"
#include"math.h"
#include"queue"
#include"algorithm"
using namespace std;
#define INF 1001010
typedef struct Node
{
    int x,y,t;
    Node(int a,int b,int c)
    {
        x = a; y = b; t = c;
    }
    Node()
    {

    }
}Node;

const int dir[4][2] = {{-1,0},{1,0},{0,1},{0,-1}};

int T,N,M;
char Graph[810][810];
int min_k;

int check(int x,int y)
{
   if(x >= 1 && x <= N && y >= 1 && y <= M)    return 1;
   return 0;
}

int bfs()
{
    queue<Node> man,girl,ghost;


    for(int i = 1; i <= N; i ++)
        {
            for(int j = 1; j <= M; j ++)
            {
                if(Graph[i][j] == 'G')
                    {
                       // printf("%c i = %d j = %d\n",Graph[i][j],i,j);
                        girl.push({i,j,0});
                    }
                if(Graph[i][j] == 'M')
                    {
                       //printf("%c i = %d j = %d\n",Graph[i][j],i,j);

                        man.push({i,j,0});
                        //vis_man[i][j] = 1;
                    }
                if(Graph[i][j] == 'Z')
                {
                    ghost.push({i,j,0});
                    //vis_woman[i][j] = 1;
                }
            }
        }
    for(int i = 1; i <= 100000; i ++)
    {
       int flag = ghost.front().t;
       while(!ghost.empty() && ghost.front().t < flag + 2)
       {
           Node T = ghost.front(); ghost.pop();
           int x = T.x;
           int y = T.y;
           for(int j = 0; j < 4;j ++)
           {
               int x1 = x + dir[j][0];
               int y1 = y + dir[j][1];
               if(check(x1,y1) && Graph[x1][y1] != '#')
               {
                   Graph[x1][y1] = '#';Graph[x][y] = '#';
                   ghost.push({x1,y1,T.t + 1});
               }
           }
       }
       flag = man.front().t;
       while(!man.empty() && man.front().t < flag + 3)
       {
           Node T = man.front(); man.pop();
           int x = T.x;
           int y = T.y;
           for(int j = 0; j < 4; j ++)
           {
               int x1 = x + dir[j][0];
               int y1 = y + dir[j][1];
               if(Graph[x1][y1] == 'G') return i;
               if(check(x1,y1) && Graph[x1][y1] == '.')
               {
                   Graph[x1][y1] = 'M'; Graph[x][y] = 'X';
                   man.push({x1,y1,T.t + 1});
               }
           }
       }
       flag = girl.front().t;
       while(!girl.empty() && girl.front().t < flag + 1)
       {
           Node T = girl.front(); girl.pop();
           int x = T.x;
           int y = T.y;
           for(int j = 0; j < 4; j ++)
           {
               int x1 = x + dir[j][0];
               int y1 = y + dir[j][1];
               if(Graph[x1][y1] == 'M') return i;
               if(check(x1,y1) && Graph[x1][y1] == '.')
               {
                   Graph[x1][y1] = 'G';Graph[x][y] = 'X';
                   girl.push({x1,y1,T.t + 1});
               }
           }
       }
    }
    return -1;
}

int main()
{
    scanf("%d",&T);
    while(T --)
    {
        scanf("%d%d",&N,&M);
        int cnt = 0;
        for(int i = 1; i <= N; i ++)
            {
               scanf("%s",Graph[i] + 1);
            }
        int T = bfs();
        printf("%d\n",T);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值