hdu1010 Tempter of the Bone

來源:互聯網
上載者:User

標籤:http   os   資料   io   for   問題   

  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. }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.