题意:有两只鬼,一个男孩女孩被困在迷宫中,男孩每秒可以走三步,女孩只能1步,鬼可以两步且可以通过墙。问男孩女孩是否可以在鬼抓住他们之前会合?

注意:每秒开始鬼先移动,然后两人开始移动。

思路:以男孩和女孩为起点进行双向bfs,鬼由于可以穿墙可以直接通过曼哈顿距离判断当前位置是否合法。注意在处理男孩移动的时,必须加入一点技巧,否则处理状态太多就会超时。我用的一种比较笨的方法处理男孩的移动结果TLE了。

AC代码: 405ms

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;

const int maxn = 800 + 5;
char G[maxn][maxn];
int vis[2][maxn][maxn];
int n, m;

struct node{
	int x, y;
	node() {
	}
	node(int x, int y): x(x), y(y){
	}
};

const int dx[] = {0,0,-1,1};
const int dy[] = {-1,1,0,0}; 

bool is_ghost(int x, int y, int step, vector<node> &p) {
	for(int i = 0; i < p.size(); ++i) {
		int px = p[i].x, py = p[i].y;
		int man = abs(x - px) + abs(y - py); //曼哈顿距离
		if(step * 2 >= man) return false;
	}
	return true;
}

queue<node>q[2];
vector<node>per, ghost;

int bfs(int c, int step) { //共有四个起点
	int num = q[c].size();
	while(num--) { //清空上一次的移动位置
		node p = q[c].front();
		q[c].pop();
		int x = p.x, y = p.y;
		if(!is_ghost(x, y, step + 1, ghost)) continue;
		for(int i = 0; i < 4; ++i) {
			int px = x + dx[i], py = y + dy[i];
			if(px < 0 || py < 0 || px >= n || py >= m) continue;
			if(vis[c][px][py] || G[px][py] == 'X' || !is_ghost(px, py, step + 1, ghost)) continue;
			if(vis[1 - c][px][py]) return 1; //找到对方
			q[c].push(node(px, py));
			vis[c][px][py] = 1;
		}
	}
	return 0;
}

int solve() {
	per.clear();
	ghost.clear();
	while(!q[0].empty()) q[0].pop();
	while(!q[1].empty()) q[1].pop();
 	memset(vis, 0, sizeof(vis));
	for(int i = 0; i < n; ++i)
	for(int j = 0; j < m; ++j) {
		if(G[i][j] == 'M') {
			per.push_back(node(i, j));
			vis[0][i][j] = 1;
			q[0].push(node(i, j));
		}
		else if(G[i][j] == 'G') {
			per.push_back(node(i, j));
			q[1].push(node(i, j));
			vis[1][i][j] = 1;
		}
		else if(G[i][j] == 'Z') {
			ghost.push_back(node(i, j));
		}
	}
	for(int i = 0; i < 2; ++i) {
		if(!is_ghost(per[i].x, per[i].y, 1, ghost)) return -1;
	}
	int step = -1;
	while(!q[0].empty() && !q[1].empty()) {
		++step;
		for(int i = 0; i < 3; ++i) {
			if(bfs(0, step)) return step + 1;
 		}
 		if(bfs(1, step)) return step + 1;
	}
	return -1;
}

int main() {
	int T;
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &n, &m);
		for(int i = 0; i < n; ++i) scanf("%s", G[i]);
		printf("%d\n", solve());
	}
	return 0;
}

如有不当之处欢迎指出!

HDU - 3085 双向BFS + 技巧处理 [kuangbin带你飞]专题二的更多相关文章

  1. HDU - 3567 Eight II (bfs预处理 + 康托) [kuangbin带你飞]专题二

    类似HDU1430,不过本题需要枚举X的九个位置,分别保存状态,因为要保证最少步数.要保证字典序最小的话,在扩展节点时,方向顺序为:down, left, right, up. 我用c++提交1500 ...

  2. HDU - 3567 IDA* + 曼哈顿距离 + 康托 [kuangbin带你飞]专题二

    这题难度颇大啊,TLE一天了,测试数据组数太多了.双向广度优先搜索不能得到字典序最小的,一直WA. 思路:利用IDA*算法,当前状态到达目标状态的可能最小步数就是曼哈顿距离,用于搜索中的剪枝.下次搜索 ...

  3. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  4. HDU - 3533 bfs [kuangbin带你飞]专题二

    看了好久的样例才看懂. 题意:有一个人要从(0,0)走到(n,m),图中有k个碉堡,每个碉堡可以向某个固定的方向每隔t秒放一次炮,炮弹不能穿越另一个碉堡,会被阻挡.人在移动的过程中不会被炮弹打到,也就 ...

  5. HDU - 1067 Gap (bfs + hash) [kuangbin带你飞]专题二

    题意:    起初定28张卡牌的排列,把其中11,  21, 31, 41移动到第一列,然后就出现四个空白,每个空白可以用它的前面一个数的下一个数填充,例如43后面的空格可以用44填充,但是47后面即 ...

  6. HDU - 2102 A计划 (BFS) [kuangbin带你飞]专题二

    思路:接BFS判断能否在限制时间内到达公主的位置,注意如果骑士进入传送机就会被立即传送到另一层,不会能再向四周移动了,例如第一层的位置(x, y, 1)是传送机,第二层(x, y, 2)也是传送机,这 ...

  7. 【算法系列学习】[kuangbin带你飞]专题二 搜索进阶 D - Escape (BFS)

    Escape 参考:http://blog.csdn.net/libin56842/article/details/41909459 [题意]: 一个人从(0,0)跑到(n,m),只有k点能量,一秒消 ...

  8. HDU - 1043 A* + 康托 [kuangbin带你飞]专题二

    这题我第一次用的bfs + ELFhash,直接TLE,又换成bfs + 康托还是TLE,5000ms都过不了!!我一直调试,还是TLE,我才发觉应该是方法的问题. 今天早上起床怒学了一波A*算法,因 ...

  9. POJ - 3126 bfs + 素数筛法 [kuangbin带你飞]专题一

    题意:给定两个四位素数作为终点和起点,每次可以改变起点数的某一位,且改变后的数仍然是素数,问是否可能变换成终点数字? 思路:bfs搜索,每次改变四位数中的某一位.素数打表方便判断新生成的数是否是素数. ...

随机推荐

  1. Python起步

    最近研究系统自动化测试想起了一年前有学习Python的想法,借此机会准备抽时间好好学学.为方便以后学习和查询特写以下博客! Python基础 1. Python数据结构 (1)Python字符串 (2 ...

  2. Servlet--HttpServlet类

    HttpServlet类 定义 public class HttpServlet extends GenericServlet implements Serializable 这是一个抽象类,用来简化 ...

  3. linkin大话面向对象--GC和jar包

    GC java的垃圾回机制是java语言的重要机制之一.当程序创建对象,数组等引用类型实体时,系统都会在堆内存中为之分配一块内存区,对象就保存在这块内存区中.当这块内存不再被任何变量引用时,这块内存就 ...

  4. 李忠益TP5商城项目笔记(待完成)

    商品种类的无限极分类 $data=db('goods_type')->field(['*','concat(path,",",id)'=>'paths'])->o ...

  5. HTTP基本知识

    1.TCP/IP 传输控制协议/因特网互联协议 (1)应用层:决定向用户提供应用服务时通信的活动(FTP.DNS和HTTP都属于该层). (2)传输层:提供处于网络连接中的两台计算机之间的数据传输(T ...

  6. c#后台调用API

    前两周赶上项目第一个版本上线,着实忙了一把,毕竟只有两个人负责.如今已完结,总算喘了一口气,现在任务就是写API.测API,许久之前写过JS前台调用 项目API,也写过后台调用开放的手机号归属地查询, ...

  7. Python随笔,day1

    #python中不存在单个字符的运算,只有字符串函数 >>> s="www.google.com" >>> s 'www.google.com' ...

  8. 删除一个目录及其子目录下的所有.svn文件

    今天建立svn,加入代码,发现这些个文件夹中竟然已经有.svn文件夹,也就是它以前使用过svn, 这下就有点麻烦,在全新的svn里,这些.svn需要删除,又不可能一个一个手工去删除 网上翻了一下,发现 ...

  9. 纯静态界面中(html)中通过js调用dll中的方法从数据库中读取数据

    最近接到一个离职员工的任务,一个搭好框架的ERP系统,看了两天,说一下看到的东西,整个项目目录中我没发现一个.aspx后缀的文件,全是静态HTML文件,之后发现他用的jquery简直看的头疼,不过大概 ...

  10. ASP.NET MVC 播放远程服务器上的MP3文件

    问题: 做需求遇到需要播放远程服务器上的MP3音频,使用FTP去获取文件.但是一般都是在页面 <audio> 的src 中直接写文件地址来播放音频.实在不想做临时文件,折腾了半天终于可以通 ...