给定一张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<8001<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
 

算法:bfs

题解:就是先枚举鬼能走到的位置,然后在枚举女孩和男孩要走到的位置,重复做这件事,直到女孩能碰到男孩,否则输出-1.因为它走过的次数不会超过1e5次(读者可以自己证明)。

#include <iostream>
#include <cstdio>
#include <queue> using namespace std; const int maxn = 1e3+; struct node {
int x, y, step;
}; char Map[maxn][maxn];
int dir[][] = {, -, , , -, , , };
int n, m; bool check(int x, int y) {
if(x <= || x > n || y <= || y > m) {
return false;
}
return true;
} int bfs() {
queue<node> girl, boy, ghost;
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
if(Map[i][j] == 'M') {
boy.push((node){i, j, });
} else if(Map[i][j] == 'G') {
girl.push((node){i, j, });
} else if(Map[i][j] == 'Z') {
ghost.push((node){i, j, });
}
}
}
for(int i = ; i <= ; i++) { //枚举来遍历这些时间
int tmp = ghost.front().step + ; //限制了移动的距离
while(!ghost.empty() && ghost.front().step < tmp) {
node now = ghost.front();
ghost.pop();
for(int j = ; j < ; j++) {
int tx = now.x + dir[j][];
int ty = now.y + dir[j][];
if(check(tx, ty) && Map[tx][ty] != '#') {
ghost.push((node){tx, ty, now.step + });
Map[tx][ty] = '#';
Map[now.x][now.y] = '#';
}
}
}
tmp = boy.front().step + ;
while(!boy.empty() && boy.front().step < tmp) {
node now = boy.front();
boy.pop();
for(int j = ; j < ; j++) {
int tx = now.x + dir[j][];
int ty = now.y + dir[j][];
if(check(tx, ty) && Map[tx][ty] != '#') {
if(Map[tx][ty] == '.') {
boy.push((node){tx, ty, now.step + });
Map[tx][ty] = 'M';
Map[now.x][now.y] = 'X';
} else if(Map[tx][ty] == 'G') {
return i;
}
}
}
}
tmp = girl.front().step + ;
while(!girl.empty() && girl.front().step < tmp) {
node now = girl.front();
girl.pop();
for(int j = ; j < ; j++) {
int tx = now.x + dir[j][];
int ty = now.y + dir[j][];
if(check(tx, ty) && Map[tx][ty] != '#') {
if(Map[tx][ty] == '.') {
girl.push((node){tx, ty, now.step + });
Map[tx][ty] = 'G';
Map[now.x][now.y] = 'X';
} else if(Map[tx][ty] == 'M') {
return i;
}
}
}
} }
return -;
} int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &m);
for(int i = ; i <= n; i++) {
getchar();
for(int j = ; j <= m; j++) {
scanf("%c", &Map[i][j]);
}
}
printf("%d\n", bfs());
}
return ;
}

AcWing:177. 噩梦(bfs)的更多相关文章

  1. Leapin' Lizards(hdu 2732)

    Leapin' Lizards Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  2. 借助Photoshop,Illustrator等设计软件进行WPF图形图像的绘制

    原文:借助Photoshop,Illustrator等设计软件进行WPF图形图像的绘制 本文所示例子是借助第三方设计软件,制作复杂的矢量图形,转成与XAML酷似的SVG,再转换成xaml而实现的. 这 ...

  3. 噩梦(双向BFS)

    给定一张N*M的地图,地图中有1个男孩,1个女孩和2个鬼. 字符“.”表示道路,字符“X”表示墙,字符“M”表示男孩的位置,字符“G”表示女孩的位置,字符“Z”表示鬼的位置. 男孩每秒可以移动3个单位 ...

  4. AcWing:176. 装满的油箱(bfs + dijiskla思想)

    有N个城市(编号0.1…N-1)和M条道路,构成一张无向图. 在每个城市里边都有一个加油站,不同的加油站的单位油价不一样. 现在你需要回答不超过100个问题,在每个问题中,请计算出一架油箱容量为C的车 ...

  5. AcWing:175. 电路维修(bfs)

    达达是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女翰翰,从而被收留在地球上. 翰翰的家里有一辆飞行车. 有一天飞行车的电路板突然出现了故障,导致无法启动. 电路板的整体结构是一个R ...

  6. AcWing:173. 矩阵距离(bfs)

    给定一个N行M列的01矩阵A,A[i][j] 与 A[k][l] 之间的曼哈顿距离定义为: dist(A[i][j],A[k][l])=|i−k|+|j−l|dist(A[i][j],A[k][l]) ...

  7. AcWing:172. 立体推箱子(bfs)

    立体推箱子是一个风靡世界的小游戏. 游戏地图是一个N行M列的矩阵,每个位置可能是硬地(用”.”表示).易碎地面(用”E”表示).禁地(用”#”表示).起点(用”X”表示)或终点(用”O”表示). 你的 ...

  8. acwing 173. 矩阵距离(bfs)

    给定一个N行M列的01矩阵A,A[i][j] 与 A[k][l] 之间的曼哈顿距离定义为: dist(A[i][j],A[k][l])=|i−k|+|j−l|dist(A[i][j],A[k][l]) ...

  9. HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ)

    HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Ja ...

随机推荐

  1. AOP的应用与基本概念(源自别人的博文)

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  2. Payload 实现分离免杀

    众所周知,目前的杀毒软件的杀毒原理主要有三种方式,一种基于特征,一种基于行为,一种基于云查杀,其中云查杀的一些特点基本上也可以概括为特征码查杀,不管是哪一种杀毒软件,都会检查PE文件头,尤其是当后门程 ...

  3. ide的debug

    webstom 新建立一个配置项 找到webpack.config.js,最后一行加上 devtool: "source-map" 然后点击debug

  4. 梯度直方图(HOG,Histogram of Gradient)

    1.介绍 HOG(Histogram of Oriented Gradient)是2005年CVPR会议上,法国国家计算机科学及自动控制研究所的Dalal等人提出的一种解决人体目标检测的图像描述子,该 ...

  5. 对vuex分模块管理

    为什么要分模块: 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象.当应用变得非常复杂时,store 对象就有可能变得相当臃肿.为了解决以上问题,Vuex 允许我们将 store 分割成模块 ...

  6. Dubbo 配置参数

    关闭启动检查 在dubbo多模块项目启动的时候为了并行启动多个服务,缩短启动时间,需要解除模块之间的依赖检测 dubbo.consumer.check=false @Reference(check = ...

  7. 19.SSM整合_配置式开发

    1.定义实体类Student 2.定义Student表 3.定义index页面 4.定义处理器 5.定义Service 6.定义Dao接口 7.定义Dao的Mapper配置文件 8.定义MyBatis ...

  8. Python3 GUI:PyQt5环境搭建

    配置镜像源 最近用Python内置的Thinter写了个小工具,发现界面略朴素,于是决定转向PyQt5.先配置镜像源,否则只能龟速下载. C:\Users\你的用户名下新建目录pip 在pip目录下新 ...

  9. 【Day4】2.详解Http请求协议

    Http请求协议

  10. zip命令分卷压缩和解压缩

    创建分卷压缩文件 zip -s 100m -r folder.zip folder/ -s: 创建分卷的大小 -r: 循环压缩文件夹下面的内容 切分已有的文件: zip existing.zip -- ...