迷宮問題求解之「窮舉 回溯」(一)

2022-07-04 17:21:19 字數 2488 閱讀 3949

求迷宮從入口到出口的所有路徑是乙個經典的程式設計問題,求解迷宮,通常採用的是「窮舉+回溯」的思想,即從入口開始,順著某乙個方向出發,若能夠走通,就繼續往前走;若不能走通,則退回原路,換乙個方向繼續向前探索,直到所有的通路都探尋為止。因此本文依據這種「窮舉+回溯」的思想,設計乙個求解迷宮的程式。

為了保證在任何位置上都能夠退回原路,顯然需要使用乙個先進後出的資料結構來儲存已經探尋過的位置,因此在程式求解迷宮路徑的過程中採用這種資料結構。

迷宮是乙個二維地圖,其中含有出口和入口,障礙點和通道,因此程式採用乙個二位陣列map來表示,其中,二維陣列值所代表的含義如下:

0:通道    1:起點    2:障礙    3:終點    4:路徑
需要注意的是,最後求解出來的通路,必須要是一條簡單路徑,即在求得的路徑上不能重複出現同一通道快。下面簡述一下程式的求解過程。

根據對迷宮問題的分析,求迷宮中一條從入口到出口的路徑演算法描述如下:

設定入口位置為當前位置。

if(當前位置是可通行且是沒有被走過的通道塊(分支1)

2.1 將當前位置壓到棧中。

2.2 若當前位置是出口,`則程式結束,返回路徑棧`。

2.3 若當前不是出口,則切換當前位置為當前位置東邊的通道塊,`返回2繼續執行`。

else(若當前位置不可通行)(分支2)

3.1 獲取棧頂元素所在的位置,若該位置所在的相鄰4個方向都被探索過了,則刪除當前棧頂元素,獲取新的棧頂元素,直到找到乙個可通的相鄰塊位置或出棧至棧空`再執行3.2步驟`。

3.2 若棧頂元素所在的位置還有其他方向沒有被探索過,則設定新的當前位置為棧頂元素的未被探索方向的相鄰通道塊。(方向訪問順序為順時針即東南西北)

重複步驟2.

需要注意步驟2中的沒有被走過的通道塊,是指該通道塊從來未壓入棧中,否則求解的路徑就不是一條簡單路徑,很可能導致乙個死迴圈。

程式採用c#語言對上述的演算法描述進行了實現,**如下。

3.1 通到塊實體

class pathelement

public int row;//位置所在的行

public int col;//位置所在的列

public int direction;//從此位置走向下一位置的方向,方向分為東0南1西2北3,預設東方向為初始方向

}

3.2 尋找簡單路徑
public static stackfindpath(int[,] map, int startx, int starty, int endx, int endy)

else//當前不能通過

if (topelement.direction < 4)}}

} while (path.count != 0);

return null;

}

3.3 輔助方法
/*獲取下乙個位置*/

private static pathelement getnextposition(pathelement curpostion)

curpostion.direction++;

return nextposition;

}/*是否為通道*/

private static bool pass(pathelement curposition, int[,] map)

else

}else

}/*是否被訪問*/

private static bool visited(pathelement curposition, listvisitedlist)

}return false;

}

3.4 介面

介面所包含的功能:

能夠編輯迷宮地圖,單擊實現障礙物的設計,雙擊去掉障礙物。

能夠儲存和載入地圖。

能夠通過該演算法實現從迷宮入口到出口路徑的生成和顯示。

3.5 結果截圖

1 地圖的載入

2 路徑尋找

「窮舉+回溯」的思路還是很好理解,通俗的講,就是選擇一條道路一直走到黑,如果碰到前方有障礙,就退回來一步再換乙個方向繼續走,直到把所有可能的路都做完了。

利用「窮舉+回溯」搜尋路徑,雖然簡單,但是它屬於一種盲目、機械的搜尋演算法,從3.5中的結果圖中可以看出,該演算法找出來的路徑,顯然不是最優的,走了許多的彎路。那麼如何從迷宮的起點到終點找到一條最優的路徑呢?請參考《迷宮問題求解之「a*搜尋」(二)》。

迷宮求解 窮舉求解法

迷宮求解是乙個理解資料結構中棧的比較好的實踐例子,下面進行分析 設迷宮是又乙個2維陣列組成的,元素只有0或1來表示是否通路,0代表通路,1代表有牆壁不通路 例如下圖中是一條通路 窮舉法 從入口出發,順某方向向前探索,如能走通,則繼續往前走,否則沿原路返回,換乙個方向再試,直到所有可能的銅鑼都探索到為...

回溯法求解迷宮問題

題目 這是我在老師發的ppt上發現的一道題,如下 1表示起點 7表示終點,一共六個路口,每個路口可以通達最多左上右三個路口,不能走的方向用0表示,求從1到7的路徑。求解思路 每個路口最多有三個搜尋分支。把演算法設計為如下的搜尋過程 把整個搜尋分解為向左 向前和向右三個方向上子問題的搜尋。當搜尋到某個...

回溯法求解迷宮問題

最近在leetcode上看了些演算法題,有些看著很簡單的很常用的東西,竟然一下子想不出來怎麼求解,比如說 實現sqrt函式,求陣列的排列。如果高數學的不好,這些看似簡單的問題,第一次碰到也會感覺很難求解,當然了,今天要說的是這樣乙個問題,求解迷宮的所有解,這個問題的求解用到了回溯法的思想,不了解這個...