深度優先搜索應用:走迷宮

走迷宮問題是深度優先搜索的一個典型應用,通常迷宮的形狀如下


這裏寫圖片描述

0爲可走的道路,1爲牆壁。通常情況下一些變種的模型,會加入一些特殊項,有別的意思,比如數字5代表鑰匙,當然複雜模型先不討論,從最簡單的開始。

深度優先搜索的思想其實就是枚舉式的遞歸,不斷的對當前狀態下進行對下一狀態轉移的進行枚舉,直到找到解。在迷宮問題中,任意一個可以走的點都有4種轉移狀態(往上,往下,往左,往右),當然不是每一種狀態的轉移都是合法的,比如,以左上角(假設)點爲起點,起點狀態無法轉移到:上,左,右這三種狀態。只有往下是可以進行轉移的,當我們往下轉移時,轉移時合法的,就遞歸進一層,此時,我們在新的狀態下,重複進行枚舉可轉移狀態並進一步遞歸進去,然後對合法的狀態進行遞歸來搜索解,當搜索到某一狀態搜索完所有可轉移的狀態時依然無法找到解,就進行回溯到上一層狀態,遞歸轉移到下一狀態。
深度優先搜索可以用樹的前序遍歷來理解,我們一直往深處走,走到頭了就往回走,然後選則另外一條路繼續往深處走,直到全部走完或這找到我們要的條件
下面結合代碼來理解

#include<iostream> 
#include<math.h>
#include<memory.h>
#include<stack>
using namespace std;
//這是設定的狀態轉移變量,分爲上下左右4組,每一組的值分別代表X,Y的偏移
int dst[4][2]={//上下左右 
                -1,0,
                1,0,
                0,-1,
                0,1
              }; 
//迷宮,終點設置爲數字3,已經走過的節點設置爲4
int  maze[5][5] = {

        0,1, 0, 0, 0,

        0,1, 0, 1, 0,

        0,0, 0, 0, 0,

        0,1, 1, 1, 0,

        0,0, 0, 1, 3,

};

void dfs(int x,int y)
{

    if(maze[x][y]==3)//判斷是否走到了終點,走到了就是輸出找到的解
    {//if裏面是對可行解的一個判斷表達式,裏面的話就執行我們得到一個解後要進行的操作。
        for(int i=0;i<5;i++)
        {
            for(int j=0;j<5;j++)
            {
                cout<<maze[i][j]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
        return ;
    }

    for(int i=0;i<4;i++)//枚舉轉移狀態
    {

        int nextx = x+dst[i][0];//計算轉移狀態
        int nexty = y+dst[i][1];
        //下面這裏就是DFS的核心部分了,判斷轉移是否合法,合法的遞歸進去,不合法的,不進行搜索,if需要包含全部判斷條件,不可缺一,否則搜索回出問題
        if(nextx>=0 && nextx<=4 && nexty>=0 && nexty<=4&&(maze[nextx][nexty]!=1)&&(maze[nextx][nexty]!=4))//判斷下一個要走的點是否合法,在迷宮的題目裏面主要是判斷轉移的點能不能走 
        {
            maze[x][y] = 4;//設置當前點爲走過   
            dfs(nextx,nexty);//進一步搜索            
            maze[x][y] = 0;//退出來設置爲沒有走過,這樣在回溯進行後續搜索時,不會影響對路徑的搜索     
        }
    }

    return ;
} 
int main()
{

  dfs(0,0);//初始調用

 return 0;

}

輸出結果
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章