转载大佬的blog,很详细,学到了很多东西

奇偶剪枝:根据题目,dog必须在第t秒到达门口。也就是需要走t-1步。设dog开始的位置为(sx,sy),目标位置为(ex,ey).如果abs(ex-x)+abs(ey-y)为偶数,则abs(ex-x)和abs(ey-y)奇偶性相同,所以需要走偶数步;

当abs(ex-x)+abs(ey-y)为奇数时,则abs(ex-x)和abs(ey-y)奇偶性不同,到达目标位置就需要走奇数步。先判断奇偶性再搜索可以节省很多时间,不然的话容易超时。t-sum为到达目标位置还需要多少步。因为题目要求doggie必须在第t秒到达门的位置,所以(t-step)和abs(ex-x)+abs(ey-y)的奇偶性必然相同。因此temp=(t-step)-abs(ex-x)+abs(ey-y)必然为偶数

http://acm.hdu.edu.cn/forum/read.php?tid=6158

  1. 1010 temp of the bone
  2. sample input:
  3. 4 4 5
  4. S.X.
  5. ..X.
  6. ..XD
  7. ....
  8. 问题:
  9. (1):
  10. 在发现当前节点无法到达时,这点弹出栈,并且把这点的标记重新刷为'.'
  11. (2):
  12. 如何在dfs中既要保证到达又要使时间正好呢?? 在函数中通过这种形式实现:
  13. dfs(int si,int sj,int cnt) 就是用cnt来记录当时的时间,并且在
  14. if( si==di && sj==dj && cnt==t )
  15. {
  16. escape = 1;
  17. return;
  18. }
  19. 的时候 即当前点到达了终点并且时间恰好等于题目所给限制时间时,跳出
  20. 并且escape标记为真
  21. (3):
  22. 如何让一个点有顺序地遍历它四周地能到达的点呢??
  23. 聪明并且简短的方法是设施一个dir[4][2] 数组 控制方向
  24. 并且设置它的值为dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
  25. 遍历的时候用for(i:0->4)就非常方便了
  26. (4):
  27. 千万要注意的是节点越界的情况, dfs(int si,int sj,int cnt)的时候一定要把 si, sj 控制在给你的矩阵内 在后面会提到一个我的列子 就是因为访问了[0, -1]的位置导致了其
  28. 他数据被更改
  29. (5):
  30. 读入矩阵的时候,可以采用for(i = 1; i <= N; i++)
  31. for(j = 1; j <= M; j++)
  32. scanf("%c", &map[i][j]);
  33. 的方法,好处在于可以控制和计算每一个读入的数据,坏处是调试的时候对矩阵的观察不太方便,而且好像还会有错误,在2102"A计划"用这种方法读入数据时好像就会wa,
  34. 另一种方法是for(i = 0; i < N; i++) gets(map[i]);
  35. 这样读入的数据在调试观察的时候十分方便 gets()读入的默认为字符串,在vc调试的时候是显式的 可以直接观察矩阵 缺点是对矩阵中各个数据的计算和控制无法实现,需要读完后再遍历一遍
  36. (6)
  37. 能用bfs还是尽量用bfs 我不会bfs.... dfs的递归在调试的时候不是很方便,而且bfs要比dfs快,调试也要方便,因为它没有递归
  38. (7)
  39. 关于剪枝,没有剪枝的搜索不太可能,这题老刘上课的时候讲过两个剪枝,一个是奇偶剪枝,一个是路径剪枝
  40. 奇偶剪枝:
  41. 把矩阵标记成如下形式:
  42. 0,1,0,1,0
  43. 1,0,1,0,1
  44. 0,1,0,1,0
  45. 1,0,1,0,1
  46. 很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步
  47. 在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) (Di+Dj) 的奇偶性就可以了
  48. 路径剪枝:
  49. 矩阵的大小是N*M 墙的数量记为wall 如果能走的路的数量 N*M - wall 小于时间T,就是说走完也不能到总的时间的,这显然是错误的,可以直接跳出了
  50. 课件里面给过这题的标程,在dfs的过程中有个没提到的剪枝,就是记录当前点到终点的最短路,如果小于剩余的时间的话,就跳出
  51. 这个剪枝我觉得更科学,它毕竟是动态的么,标程里面是这么写的:
  52. temp = (t-cnt) - abs(si-di) - abs(sj-dj);
  53. if( temp<0 || temp&1 ) return;
  54. 其中求当前点到终点的最短路是这样 abs(si-di) - abs(sj-dj) 这个就比较粗糙了 明显没有考虑到碰到墙要拐弯的情况
  55. 那求最短路有没有什么好办法呢?
  56. 我曾经想到过用 Dijkstraq求最短路的 ,明显大才小用,在论坛里看到一个方法觉得可以用在这里
  57. 给定下例:
  58. S.X.
  59. ..X.
  60. ..XD
  61. ....
  62. 每个点到终点的最短路是不是这样呢:
  63. S6X2
  64. 65X1
  65. 54XD
  66. 4321
  67. 这怎么求呢??从终点开始遍历整个数组,终点是0,它周围的点都+1,墙就不计数,依次类推,就能求得这个矩阵的一个最短时间矩阵,在dfs的时候比较当前点到终点的最短路,如果大于剩余时间的话就跳出
  68. 这个方法的预处理还是非常快的,我没有用过,但是感觉会非常有用处.
  69. (8)
  70. 在做这题的时候,我碰到过一个神奇的事情,在程序运行至下面代码时
  71. if( map[ si+dir[i][0] ][ sj+dir[i][1] ] != 'X')
  72. map[ si+dir[i][0] ][ sj+dir[i][1] ] = 'X';
  73. T被改变了!! 这丝毫和T没有关系啊,怎么改变T的值呢??
  74. 原来在起点map[0][0]进入时,我没有注意到map[ si+dir[i][0] ][ sj+dir[i][1] ] 实际做的是map[0][-1] = 'X'; 很危险的一个赋值,书本上千万次强调的东西让我碰上了,这个地方我找了很久,因此我觉得有必要单独列出来提醒自己
  75. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  76. 下面我把一个带注释的标程贴一下,不是我写的注释
  77. //zju 2110 Tempter of the Bone
  78. #include <stdio.h>
  79. #include <iostream>
  80. #include <string.h>
  81. #include <stdlib.h>
  82. using namespace std;
  83. //迷宫地图
  84. //X: 墙壁,小狗不能进入
  85. //S: 小狗所处的位置
  86. //D: 迷宫的门
  87. //. : 空的方格
  88. char map[9][9];
  89. int n,m,t,di,dj; //(di,dj):门的位置
  90. bool escape;
  91. int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; //分别表示下、上、左、右四个方向
  92. void dfs(int si,int sj,int cnt) //表示起始位置为(si,sj),要求在第cnt秒达到门的位置
  93. {
  94. int i,temp;
  95. if( si>n || sj>m || si<=0 || sj<=0 ) return;
  96. if( si==di && sj==dj && cnt==t )
  97. {
  98. escape = 1;
  99. return;
  100. }
  101. //abs(x-ex) + abs(y - ey)表示现在所在的格子到目标格子的距离(不能走对角线)
  102. //t-cnt是实际还需要的步数,将他们做差
  103. //如果temp < 0或者temp为奇数,那就不可能到达!
  104. temp = (t-cnt) - abs(si-di) - abs(sj-dj);
  105. if( temp<0 || temp&1 ) return;
  106. for( i=0; i<4; i++ )
  107. {
  108. if( map[ si+dir[i][0] ][ sj+dir[i][1] ] != 'X')
  109. {
  110. map[ si+dir[i][0] ][ sj+dir[i][1] ] = 'X';
  111. dfs(si+dir[i][0], sj+dir[i][1], cnt+1);
  112. if(escape) return;
  113. map[ si+dir[i][0] ][ sj+dir[i][1] ] = '.';
  114. }
  115. }
  116. return;
  117. }
  118. int main()
  119. {
  120. int i,j,si,sj;
  121. while( cin >> n >> m >> t)
  122. {
  123. if( n==0 && m==0 && t==0 )
  124. break;
  125. int wall = 0;
  126. for( i=1; i<=n; i++ )
  127. for( j=1; j<=m; j++ )
  128. {
  129. cin >> map[i][j];
  130. if(map[i][j]=='S') { si=i; sj=j; }
  131. else if( map[i][j]=='D' ) { di=i; dj=j; }
  132. else if( map[i][j]=='X' ) wall++;
  133. }
  134. if( n*m-wall <= t )
  135. {
  136. cout << "NO" << endl;
  137. continue;
  138. }
  139. escape = 0;
  140. map[si][sj] = 'X';
  141. dfs( si, sj, 0 );
  142. if( escape ) cout << "YES" << endl;
  143. else cout << "NO" << endl;
  144. }
  145. return 0;
  146. }
  147. 这个注释当初还是帮了我很大忙的,起码让我看懂了课件

  1.  

HDU 1010 temp of the bone 解题报告 (DFS)的更多相关文章

  1. HDU 1010 Tempter of the Bone (ZOJ 2110) DFS+剪枝

    传送门: HDU:http://acm.hdu.edu.cn/showproblem.php?pid=1010 ZOJ:http://acm.zju.edu.cn/onlinejudge/showPr ...

  2. HDU 1010 Tempter of the Bone --- DFS

    HDU 1010 题目大意:给定你起点S,和终点D,X为墙不可走,问你是否能在 T 时刻恰好到达终点D. 参考: 奇偶剪枝 奇偶剪枝简单解释: 在一个只能往X.Y方向走的方格上,从起点到终点的最短步数 ...

  3. hdu 1010 Tempter of the Bone 奇偶剪枝

      如果所给的时间(步数) t 小于最短步数path,那么一定走不到. 若满足t>path.但是如果能在恰好 t 步的时候,走到出口处.那么(t-path)必须是二的倍数. 关于第二种方案的解释 ...

  4. 题解报告:hdu 1010 Tempter of the Bone

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 Problem Description The doggie found a bone in a ...

  5. HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目大意: 输入 n m t,生成 n*m 矩阵,矩阵元素由 ‘.’ 'S' 'D' 'X' 四 ...

  6. hdu - 1010 Tempter of the Bone (dfs+奇偶性剪枝) && hdu-1015 Safecracker(简单搜索)

    http://acm.hdu.edu.cn/showproblem.php?pid=1010 这题就是问能不能在t时刻走到门口,不能用bfs的原因大概是可能不一定是最短路路径吧. 但是这题要过除了细心 ...

  7. HDU 1010 Tempter of the Bone【DFS经典题+奇偶剪枝详解】

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  8. HDU 1010 Tempter of the Bone(深度+剪枝)

    http://acm.hdu.edu.cn/showproblem.php?pid=1010 题意:就是给出了一个迷宫,小狗必须经过指定的步数到达出口,并且每个格子只能走一次. 首先先来介绍一下奇偶性 ...

  9. hdu.1010.Tempter of the Bone(dfs+奇偶剪枝)

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

随机推荐

  1. jQuery插件之路(二)——轮播

    还记得以前刚接触前端的时候,浏览各大网站,很多都少不了的有个轮播的效果,那个时候自己是一个彻彻底底的小白,想着这些图片滚动起来还真是有意思,是什么让这些图片在一个方向上连续的滚动呢.后来慢慢的接触多了 ...

  2. extjs4 表单验证自定义

    extjs4 在验证上面支持的也特别好,他可以使用自带的格式验证,也可以自定义验证 比如:正则验证,密码重复填写对比验证,以及 调用后台方法验证,下面将验证方法统一写出以供参考 function lo ...

  3. jenkins部署自动化项目备注

    一.定时任务部署: 第一个*表示分钟,取值0~59 第二个*表示小时,取值0~23 第三个*表示一个月的第几天,取值1~31 第四个*表示第几月,取值1~12 第五个*表示一周中的第几天,取值0~7, ...

  4. alluxio2.0特性-预览

    项目地址 https://github.com/Alluxio/alluxio/tree/branch-2.0-preview 2.0版本-构思和设计 支持超大规模数据工作负载 Alluxio作为计算 ...

  5. 使用CXF实现WebService

    一.首先创建一个maven项目,引入相应的jar包 <?xml version="1.0" encoding="UTF-8"?> <proje ...

  6. 开园第一篇---有关tensorflow加载不同模型的问题

    写在前面 今天刚刚开通博客,主要想法跟之前某位博主说的一样,希望通过博客园把每天努力的点滴记录下来,也算一种坚持的动力.我是小白一枚,有啥问题欢迎各位大神指教,鞠躬~~ 换了新工作,目前手头是OCR项 ...

  7. 实现ssr服务端渲染demo

    最近在研究SSR服务器端渲染,自己写了的小demo. 项目布局 ├── build // 配置文件 │   │── webpack.base // 公共配置 │   │── webpack.clien ...

  8. 二.Google黑客语法

    搜索也是一门艺术! 说起Google,可谓是无人不知无人不晓,其强大的搜索功能,可以让你在瞬间找到你想要的一切.对于黑客而言,Google可是 一款绝佳的黑客工具.正因Google强大的检索能力,黑客 ...

  9. Jedis的配置和优化

    参数名:maxTotal 含义:资源池最大连接数 [默认值:8] 使用建议:需要考虑以下几点 1.业务希望的Redis并发量 2.客户端执行命令时间 3.Redis资源:例如应用个数(客户端)* ma ...

  10. LCA最近公共祖先---倍增法笔记

    先暂时把模板写出来,A几道题再来补充 此模板也是洛谷上的一道模板题 P3379 [模板]最近公共祖先(LCA) #pragma GCC optimize(2) //o2优化 #include < ...