• hdu1010 Tempter of the Bone


    1. 转载自:http://acm.hdu.edu.cn/forum/read.php?tid=6158
    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.    
    97.     if( si==di && sj==dj && cnt==t )
    98.     {
    99.         escape = 1;
    100.         return;
    101.     }
    102.    
    103.     //abs(x-ex) + abs(y - ey)表示现在所在的格子到目标格子的距离(不能走对角线)
    104.     //t-cnt是实际还需要的步数,将他们做差
    105.     //如果temp < 0或者temp为奇数,那就不可能到达!
    106.     temp = (t-cnt) - abs(si-di) - abs(sj-dj);
    107.    
    108.     if( temp<0 || temp&1 ) return;
    109.    
    110.     for( i=0; i<4; i++ )
    111.     {
    112.         if( map[ si+dir[i][0] ][ sj+dir[i][1] ] != 'X')
    113.         {
    114.             map[ si+dir[i][0] ][ sj+dir[i][1] ] = 'X';
    115.                
    116.                 dfs(si+dir[i][0], sj+dir[i][1], cnt+1);
    117.            
    118.             if(escape) return;
    119.            
    120.             map[ si+dir[i][0] ][ sj+dir[i][1] ] = '.';
    121.         }
    122.     }
    123.    
    124.     return;
    125. }
    126. int main()
    127. {
    128.     int i,j,si,sj;
    129.    
    130.     while( cin >> n >> m >> t)
    131.     {
    132.         if( n==0 && m==0 && t==0 )
    133.             break;
    134.    
    135.         int wall = 0;
    136.         for( i=1; i<=n; i++ )
    137.             for( j=1; j<=m; j++ )
    138.             {
    139.                 cin >> map[i][j];
    140.                 if(map[i][j]=='S') { si=i; sj=j; }
    141.                 else if( map[i][j]=='D' ) { di=i; dj=j; }
    142.                 else if( map[i][j]=='X' ) wall++;
    143.             }
    144.            
    145.             if( n*m-wall <= t )
    146.             {
    147.                 cout << "NO" << endl;
    148.                 continue;
    149.             }
    150.            
    151.             escape = 0;
    152.             map[si][sj] = 'X';
    153.            
    154.             dfs( si, sj, 0 );
    155.            
    156.             if( escape ) cout << "YES" << endl;
    157.             else cout << "NO" << endl;
    158.     }
    159.    
    160.     return 0;
    161. }
  • 相关阅读:
    访问修饰符的权限。
    字符编码
    3/11 作业
    3/10 作业
    作业 3/9
    流程控制之for循环
    Exception in createBlockOutputStream
    windows上传文件到 linux的hdfs
    win10 配置 hadoop-2.7.2
    hadoop 源码编译
  • 原文地址:https://www.cnblogs.com/duan-to-success/p/3854988.html
Copyright © 2020-2023  润新知