噩梦(双向BFS)
给定一张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。
每个结果占一行。
emmmmm, 当时就打了个测试程序就回班了, 回来之后看到我的代码里有这个东西:

啊啊啊, 孟神, 你的算法进阶真不是我拿的啊。
进入正题--
求步数的话我们很容易想到BFS, 但这是两个人, 其实也很容易想到双向BFS, 创建两个队列, 在合法的状态下同时搜索, 当一个人搜索到另一个点人访问过的点时, 此时的步数就是最少步数;
#include <bits/stdc++.h> using namespace std; typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + ;
const int MAXM = 3e3 + ; template < typename T > inline void read(T &x) {
x = ; T ff = , ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') ff = -;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << ) + (x << ) + (ch ^ );
ch = getchar();
}
x *=ff;
} template < typename T > inline void write(T x) {
if(x < ) putchar('-'), x = -x;
if(x > ) write(x / );
putchar(x % + '');
} int T, n, m;
int vis[MAXM][MAXM];
int dx[] = {, , -, };
int dy[] = {, , , -};
char ch[MAXM][MAXM];
pair < int, int > boy, girl, ghost[]; // 梁神我的算法进阶是不是在你那 -- msm inline bool check(int xx, int yy, int dis) {
if(xx < || xx >= n || yy < || yy >= m || ch[xx][yy] == 'X') return false;
for(int i = ; i < ; ++i) {
if(abs(xx - ghost[i].first) + abs(yy - ghost[i].second) <= * dis) return false;
}
return true;
} inline int BFS() {
memset(vis, , sizeof(vis));
queue < pair < int, int > > qb, qg;
qb.push(boy);
qg.push(girl);
int dis = ;
while(!qb.empty() || !qg.empty()) {
++dis;
for(int i = ; i < ; ++i) {
int len = qb.size();
for(int j = ; j < len; ++j) {
pair < int, int > x;
x = qb.front();
qb.pop();
int a = x.first, b = x.second;
if(!check(a, b, dis)) continue;
for(int k = ; k < ; ++k) {
int u = a + dx[k], v = b + dy[k];
if(check(u, v, dis)) {
if(vis[u][v] == ) return dis;
if(!vis[u][v]) {
vis[u][v] = ;
qb.push({u, v});
}
}
}
}
}
int len = qg.size();
for(int i = ; i < len; ++i) {
pair < int, int > x;
x = qg.front();
qg.pop();
int a = x.first, b = x.second;
if(!check(a, b, dis)) continue;
for(int k = ; k < ; ++k) {
int u = a + dx[k], v = b + dy[k];
if(check(u, v, dis)) {
if(vis[u][v] == ) return dis;
if(!vis[u][v]) {
vis[u][v] = ;
qg.push({u, v});
}
}
}
} }
return -;
} int main() {
read(T);
while(T--) {
read(n); read(m);
for(int i = ; i < n; ++i) {
scanf("%s", ch[i]);
}
int tot = ;
for(int i = ; i < n; ++i) {
for(int j = ; j < m; ++j) {
if(ch[i][j] == 'M') boy = {i, j};
else if(ch[i][j] == 'G') girl = {i, j};
else if(ch[i][j] == 'Z') ghost[tot++] = {i ,j};
}
}
write(BFS());
puts("");
}
return ;
}
噩梦(双向BFS)的更多相关文章
- POJ1915Knight Moves(单向BFS + 双向BFS)
题目链接 单向bfs就是水题 #include <iostream> #include <cstring> #include <cstdio> #include & ...
- HDU 3085 Nightmare II 双向bfs 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...
- POJ 3170 Knights of Ni (暴力,双向BFS)
题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...
- [转] 搜索之双向BFS
转自:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx 如果目标也已知的话,用双向BFS能很大程度上提高速度. 单向时,是 b^le ...
- 双向BFS
转自“Yuan” 如果目标也已知的话,用双向BFS能很大提高速度 单向时,是 b^len的扩展. 双向的话,2*b^(len/2) 快了很多,特别是分支因子b较大时 至于实现上,网上有些做法是用两个 ...
- HDU 3085 Nightmare Ⅱ (双向BFS)
Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 3085 Nightmare Ⅱ 双向BFS
题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...
- POJ 3126 Prime Path 解题报告(BFS & 双向BFS)
题目大意:给定一个4位素数,一个目标4位素数.每次变换一位,保证变换后依然是素数,求变换到目标素数的最小步数. 解题报告:直接用最短路. 枚举1000-10000所有素数,如果素数A交换一位可以得到素 ...
- Hdu1401-Solitaire(双向bfs)
Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered ...
随机推荐
- 开发者福音!面向Web场景的云开发服务正式开放!
导 语 继支持小程序开发之后,云开发也支持Web使用啦!开发者们可以使用云开发提供的云端能力,直接开发网站应用,如PC端网页.公众号中的网页等.由此开发者可以在网站应用中借助云函数实现业务逻辑,通过与 ...
- java练习---4
//程序员:罗元昊 2017.9.17 今天好累吖咦吖咦吖 package demo;import java.util.Scanner;public class Lk { public static ...
- java 第二章
变量:变量就是代表程序运行时存放数据的地方 数据存放在:磁盘,内存卡,U盘,光盘,内存条,固态硬盘,机械硬盘等 字节:8个二进制位构成1个"字节(Byte)",它是存储空间的基本计 ...
- 【Java例题】8.1手工编写加法器的可视化程序
1. 手工编写加法器的可视化程序. 一个Frame窗体容器,布局为null,三个TextField组件,一个Button组件. Button组件上添加ActionEvent事件监听器ActionLis ...
- 利用反射,更改string对象的value数组以达到改变string值。
package test; import java.lang.reflect.Field; import lombok.Value; public class Test1{ public static ...
- 算法与数据结构基础 - 字典树(Trie)
Trie基础 Trie字典树又叫前缀树(prefix tree),用以较快速地进行单词或前缀查询,Trie节点结构如下: //208. Implement Trie (Prefix Tree)clas ...
- 最简单的DWR例子
什么是DWR? DWR是一个Open Source的 java项目.DWR可以让JavaScript调用运行在Web服务器里面的JAVA程序.简单一点或者专业一点就是Easy AJAX for JAV ...
- 同“窗”的较量:部署在 Windows 上的 .NET Core 版博客站点发布上线
为了验证 docker swarm 在高并发下的性能问题,周一我们发布了使用 docker-compose 部署的 .net core 版博客站点(博文链接),但由于有1行代码请求后端 web api ...
- html5标签整理
html元素 基础标签 <!DOCTYPE> 定义文档类型(e.g <!DOCTYPE html>) <html>定义一个HTML文档</html> ...
- EMCAscript6随心所记
es6的支持情况http://kangax.github.io/compat-table/es6/ 1.let命令 基本用法 ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变 ...