噩梦(双向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 ...
随机推荐
- RobotFramework_4.SeleniumLibrary操作(二)
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- 应用性能测试神器 Gatling,你用过吗?
在应用程序上线之前,有多少人做过性能测试? 估计大部分开发者更多地关注功能测试,并且会提供一些单元测试和集成测试的用例.然而,有时候性能漏洞导致的影响比未发现的业务漏洞更严重,因为性能漏洞影响的是整个 ...
- 常用服务部署脚本(nodejs,pyenv,go,redis,)
根据工作总结的常用安装脚本,要求linux-64系统 #!/bin/bash path=/usr/local/src node () { cd $path #wget https://nodejs.o ...
- .NET Core on K8S学习实践系列文章索引(Draft版)
一.关于这个系列 自从去年(2018年)底离开工作了3年的M公司加入X公司之后,开始了ASP.NET Core的实践,包括微服务架构与容器化等等.我们的实践是渐进的,当我们的微服务数量到了一定值时,发 ...
- JAVA-Spring AOP五大通知类型
一.前置通知 在目标方法执行之前执行的通知 在前置通知方法,可以没有参数,也可以额外接收一个JoinPoint,Spring会自动将该对象传入,代表当前的连接点,通过该对象可以获取目标对象和目标方法相 ...
- python3 实现多域名批量访问特定目录(一)
渗透测试之批量处理同一框架CMS系统漏洞 当我们做多网站的渗透测试时,会发现很多站点采用的都是同类型的CMS框架,只要我们发现一个漏洞,那么我们可以批量处理这一类站点,高效测试,如果不知道该站点的框架 ...
- jenkins弱口令漏洞
jenkins弱口令漏洞 一.漏洞描述 通过暴力破解管理控制台,如果爆破成功,可获得后台管理权限.操作后台,后台可通过脚本命令行功能执行系统命令,如反弹shell等,低权限可以通过创建控制台输出方式执 ...
- 云计算网络基础笔记及VLAN交换机配置
- WPF:window设置单一开启
方法一: Window window = new Window();window.ShowDialog; 方法二: 设置一个判断窗口打开状态的全局控制变量 private bool i ...
- hadoop学习(四)----windows环境下安装hadoop
因为我们不能在线上环境进行调试hadoop,这样就只能在本地先调试好了再放到线上去啦.我本地是windows环境,今天先记下windows下搭建hadoop2.7的步骤. 1 本地环境 windows ...