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

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

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

AC代码: 405ms

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<queue>
  5. #include<vector>
  6. #include<cmath>
  7. using namespace std;
  8.  
  9. const int maxn = 800 + 5;
  10. char G[maxn][maxn];
  11. int vis[2][maxn][maxn];
  12. int n, m;
  13.  
  14. struct node{
  15. int x, y;
  16. node() {
  17. }
  18. node(int x, int y): x(x), y(y){
  19. }
  20. };
  21.  
  22. const int dx[] = {0,0,-1,1};
  23. const int dy[] = {-1,1,0,0};
  24.  
  25. bool is_ghost(int x, int y, int step, vector<node> &p) {
  26. for(int i = 0; i < p.size(); ++i) {
  27. int px = p[i].x, py = p[i].y;
  28. int man = abs(x - px) + abs(y - py); //曼哈顿距离
  29. if(step * 2 >= man) return false;
  30. }
  31. return true;
  32. }
  33.  
  34. queue<node>q[2];
  35. vector<node>per, ghost;
  36.  
  37. int bfs(int c, int step) { //共有四个起点
  38. int num = q[c].size();
  39. while(num--) { //清空上一次的移动位置
  40. node p = q[c].front();
  41. q[c].pop();
  42. int x = p.x, y = p.y;
  43. if(!is_ghost(x, y, step + 1, ghost)) continue;
  44. for(int i = 0; i < 4; ++i) {
  45. int px = x + dx[i], py = y + dy[i];
  46. if(px < 0 || py < 0 || px >= n || py >= m) continue;
  47. if(vis[c][px][py] || G[px][py] == 'X' || !is_ghost(px, py, step + 1, ghost)) continue;
  48. if(vis[1 - c][px][py]) return 1; //找到对方
  49. q[c].push(node(px, py));
  50. vis[c][px][py] = 1;
  51. }
  52. }
  53. return 0;
  54. }
  55.  
  56. int solve() {
  57. per.clear();
  58. ghost.clear();
  59. while(!q[0].empty()) q[0].pop();
  60. while(!q[1].empty()) q[1].pop();
  61. memset(vis, 0, sizeof(vis));
  62. for(int i = 0; i < n; ++i)
  63. for(int j = 0; j < m; ++j) {
  64. if(G[i][j] == 'M') {
  65. per.push_back(node(i, j));
  66. vis[0][i][j] = 1;
  67. q[0].push(node(i, j));
  68. }
  69. else if(G[i][j] == 'G') {
  70. per.push_back(node(i, j));
  71. q[1].push(node(i, j));
  72. vis[1][i][j] = 1;
  73. }
  74. else if(G[i][j] == 'Z') {
  75. ghost.push_back(node(i, j));
  76. }
  77. }
  78. for(int i = 0; i < 2; ++i) {
  79. if(!is_ghost(per[i].x, per[i].y, 1, ghost)) return -1;
  80. }
  81. int step = -1;
  82. while(!q[0].empty() && !q[1].empty()) {
  83. ++step;
  84. for(int i = 0; i < 3; ++i) {
  85. if(bfs(0, step)) return step + 1;
  86. }
  87. if(bfs(1, step)) return step + 1;
  88. }
  89. return -1;
  90. }
  91.  
  92. int main() {
  93. int T;
  94. scanf("%d", &T);
  95. while(T--) {
  96. scanf("%d%d", &n, &m);
  97. for(int i = 0; i < n; ++i) scanf("%s", G[i]);
  98. printf("%d\n", solve());
  99. }
  100. return 0;
  101. }

如有不当之处欢迎指出!

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. 函数式编程--使用lambda表达式

    前面一篇博客我们已经说到了,lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口的实例.现在我们来写一段java的命令者模式来自己研究下lambda表达式的语法. 这里重复下命令者模式: ...

  2. 在 Tomcat 上配置虚拟主机

    .Tomcat 服务器的server.xml文件   (1)Tomcat 组件 Tomcat服务器是由一系列可配置的组件构成,其中核心组件是 Catalina Servlet 容器,它是所有其他 To ...

  3. 在Intellij IDEA 中clean报错:-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.

    解决办法:添加VM属性   -Dmaven.multiModuleProjectDirectory=$M2_HOME

  4. git 不成功

    fatal: Interactive git shell is not enabled.hint: ~/git-shell-commands should exist and have read an ...

  5. Object对象和function对象

    Obejct对象 1.ECMAScript 中的 Object 对象与 Java 中的 java.lang.Object 相似. 2.ECMAScript中的所有对象都由Object对象继承而来,Ob ...

  6. cat写入数据

    1.cat可以利用两个>>把内容追加到文件中 cat >>oldboy.txt<<EOF >1 >2 >EOF 会在文件中加入EOF中间的数据.E ...

  7. python _init_学习

    今天继续学习python,接触了_init_,感觉很好玩照着教程手写了一些代码,感觉编程语言是互通的,只是换个了形式来表达 #coding=utf-8#类似于java的构造器class Person: ...

  8. 这可能是我觉得最折腾的C++环境配置(编码+调试)--mac+eclipse

    本着造福大众的心态,万一可能有人喜欢这种环境开发呢对吧~~折腾了一天,又是谷歌又是百度,讲真遇到报错问题搜出的资料挺少的,看来用这类环境开发C++的人不多,毕竟谁没事干放着xcode,vscode不用 ...

  9. jQuery源码逐行分析学习01(jQuery的框架结构简化)

    最近在学习jQuery源码,在此,特别做一个分享,把所涉及的内容都记录下来,其中有不妥之处还望大家指出,我会及时改正.望各位大神不吝赐教!同时,这也是我的第一篇前端技术博客,对博客编写还不是很熟悉,美 ...

  10. 洛谷 [P2486] 染色

    树剖+线段树维护连续相同区间个数 注意什么时候长度要减一 #include <iostream> #include <cstdio> #include <cstdlib& ...