搜尋入門之dfs--經典的迷宮問題解析

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   strong   

今天來談一下dfs的入門,以前看到的dfs入門,那真的是入門嗎,都是把dfs的實現步驟往那一貼,看完是知道dfs的步驟了,但是對於代碼實現還是沒有概念。今天準備寫點自己的心得,真的是字面意思--入門。

 

DFS,即深度優先搜尋,是一種每次搜尋都向儘可能深的地方去搜尋,到達盡頭時再回溯進行其他結點去搜尋的搜尋策略。形象的說,這是一種“不撞南牆不回頭”的策略。

 

其實也就是遍曆,只不過不像一個線性數組的遍曆那麼直觀罷了。說到回溯,每次看到這個詞我都得思考一會,到底是怎麼用棧進行回溯的呢?今天實際操作了一次bfs,才發現妹的,這個事都是交給編譯器去完成的(只要寫的是遞迴形式)...當然了,非遞迴形式的dfs實現,肯定是要自己做棧的...

 

 

迷宮問題

迷宮問題是dfs入門的一個經典問題,這裡就以HDOJ 1010 Tempter of Bone 來談談如何實際運用dfs。

http://acm.hdu.edu.cn/showproblem.php?pid=1010

題目大意:                    

                          S.X.

                          ..X.

                          ..XD

                          ....

給出一個由以上四種符號組成的“迷宮”,‘.’代表可以通行的塊,‘X’代表牆不能通過,‘S’代表起點,‘D’代表終點,每秒都必須且只能走一步(上、下、左、右),判斷能否恰好在第T秒,到達終點D。其中每次走過的‘.’塊都會立刻消失不能再走。

 

當然了,演算法就是dfs了,其實也就是暴力枚舉,對走的每一步都進行4個方向上的分支判斷,再加上一定的剪枝,捨去一些明顯不合題意的結果,以滿足時間上的要求。

先貼上代碼吧:

 1 #include<cstdlib> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 char map[9][9];//輸入的迷宮矩陣 6 int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};//4個方向 7 int OK = 0; 8 int N, M, T, si, sj, di, dj; 9 int dfs(int si, int sj, int cnt)10 {11     if (si <= 0 || sj <= 0 || si > N || sj > M)//超出邊界就說明這條路已經死了,則返回12     {13         return 0;14     }15     if (si == di && sj == dj && cnt == T)//找到終點就返回,把標誌位置為116     {17         OK = 1;18     }19     if (OK)20     {21         return 1;22     }23     int temp = T - cnt - abs(di - si) - abs(dj - sj);//這裡就是剪枝,開始沒寫這裡,Time Limit Exceeded了十幾次...下面細談24     if (temp < 0 || temp & 1)25     {26         return 0;27     }28     for (int i = 0; i < 4; ++i)//對走到的每個結點都進行四個方向的探索29     {30         if (map[si+dir[i][0]][sj+dir[i][1]] != ‘X‘)31         {32             map[si+dir[i][0]][sj+dir[i][1]] = ‘X‘;//走過的路不能走,就先置為牆33             dfs(si+dir[i][0], sj+dir[i][1], cnt + 1);34             map[si+dir[i][0]][sj+dir[i][1]] = ‘.‘;//探索下一條路時,這個結點要恢複成可以走的狀態35         }36     }37     return 0;38 }39 int main()40 {41     while(cin >> N >> M >> T)42     {43         int wall = 0;44         OK = 0;45         if (N == 0 && M == 0 && T == 0)46         {47             break;48         }49         for (int i = 1; i <= N; ++i)50         {51             for (int j = 1; j <= M; ++j)52             {53                 cin >> map[i][j];//這裡開始還寫的scanf("%c", &map[i][j]);蠢的不談了...  不過可以這樣在for(i)的迴圈裡面寫 scanf("%s", &map[i]);54                 if (map[i][j] == ‘S‘)55                 {56                     si = i;57                     sj = j;58                 }else if (map[i][j] == ‘D‘)59                 {60                     di = i;61                     dj = j;62                 }else if (map[i][j] == ‘X‘)63                 {64                     wall++;65                 }66             }67         }68         if (N * M - wall <= T)//一個小剪枝69         {70             cout << "NO" << endl;71             continue;72         }73         map[si][sj] = ‘X‘;74         dfs(si, sj, 0);75         if (OK)76         {77             cout << "YES" << endl;78         }else79         {80             cout << "NO" << endl;81         }82     }83     return 0;84 }

先藉助代碼談一下dfs的過程:

從S開始,i = 0,往右探索,只要沒有return,就一直往右走,return了就回溯,回溯的過程呢,就是從i = 0轉到i = 1了,這就是回溯的實現過程...

 

一個小技巧,初始化這個迷宮矩陣的時候,i = 0 , j = 0, i = n + 1, j = m + 1都進行初始化,但是不儲存資料,這樣相當於在迷宮外面的四面都加上了牆,這樣在dfs過程中就不用判斷是否出界了...

 

下面談一下剪枝:

1、如果可走的塊數小於T,則肯定不能到達,這就是main()中的那個小剪枝

2、奇偶性剪枝

可以把map看成這樣:0 1 0 1 0 11 0 1 0 1 00 1 0 1 0 11 0 1 0 1 00 1 0 1 0 1從為 0 的格子走一步,必然走向為 1 的格子從為 1 的格子走一步,必然走向為 0 的格子即:  0 ->1或1->0 必然是奇數步  0->0 走1->1 必然是偶數步 結論:

  所以當遇到從 0 走向 0 但是要求時間是奇數的,或者, 從 1 走向 0 但是要求時間是偶數的 都可以直接判斷不可達!

這就是dfs中那個剪枝,也就是最主要的剪枝,其中用了&與運算來判斷是不是偶數...

 

提醒:

演算法中最基本和常用的是搜尋,這裡要說的是,有些初學者在學習這些搜尋基本演算法是不太注意剪枝,這是十分不可取的,因為所有搜尋的題目給你的測試案例都不會有很大的規模,你往往察覺不出程式啟動並執行時間問題,但是真正的測試資料一定能過濾出那些沒有剪枝的演算法。

實際上參賽選手基本上都會使用常用的搜尋演算法,題目的區分度往往就是建立在諸如剪枝之類的最佳化上了。 ”

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.