求迷宮從入口到出口的所有路徑是乙個經典的程式設計問題,求解迷宮,通常採用的是「窮舉+回溯」的思想,即從入口開始,順著某乙個方向出發,若能夠走通,就繼續往前走;若不能走通,則退回原路,換乙個方向繼續向前探索,直到所有的通路都探尋為止。因此本文依據這種「窮舉+回溯」的思想,設計乙個求解迷宮的程式。為了保證在任何位置上都能夠退回原路,顯然需要使用乙個先進後出的資料結構來儲存已經探尋過的位置,因此在程式求解迷宮路徑的過程中採用
棧
這種資料結構。
迷宮是乙個二維地圖,其中含有出口和入口,障礙點和通道,因此程式採用乙個二位陣列map來表示,其中,二維陣列值所代表的含義如下:
0:通道 1:起點 2:障礙 3:終點 4:路徑
需要注意的是,最後求解出來的通路,必須要是一條簡單路徑,即在求得的路徑上不能重複出現同一通道快。下面簡述一下程式的求解過程。
根據對迷宮問題的分析,求迷宮中一條從入口到出口的路徑演算法描述如下:
設定入口位置為當前位置。
if(當前位置是可通行且是沒有被走過的通道塊)(分支1)
else(若當前位置不可通行)2.1 將當前位置壓到棧中。
2.2 若當前位置是出口,`則程式結束,返回路徑棧`。
2.3 若當前不是出口,則切換當前位置為當前位置東邊的通道塊,`返回2繼續執行`。
(分支2)
3.1 獲取棧頂元素所在的位置,若該位置所在的相鄰4個方向都被探索過了,則刪除當前棧頂元素,獲取新的棧頂元素,直到找到乙個可通的相鄰塊位置或出棧至棧空`再執行3.2步驟`。
3.2 若棧頂元素所在的位置還有其他方向沒有被探索過,則設定新的當前位置為棧頂元素的未被探索方向的相鄰通道塊。(方向訪問順序為順時針即東南西北)
重複步驟2
.
需要注意步驟2中的沒有被走過的通道塊
,是指該通道塊從來未壓入棧中,否則求解的路徑就不是一條簡單路徑,很可能導致乙個死迴圈。
程式採用c#語言對上述的演算法描述進行了實現,**如下。
3.1 通到塊實體
3.2 尋找簡單路徑class pathelement
public int row;//位置所在的行
public int col;//位置所在的列
public int direction;//從此位置走向下一位置的方向,方向分為東0南1西2北3,預設東方向為初始方向
}
3.3 輔助方法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.4 介面/*獲取下乙個位置*/
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.5 結果截圖
1 地圖的載入
2 路徑尋找
「窮舉+回溯」的思路還是很好理解,通俗的講,就是選擇一條道路一直走到黑,如果碰到前方有障礙,就退回來一步再換乙個方向繼續走,直到把所有可能的路都做完了。
利用「窮舉+回溯」搜尋路徑,雖然簡單,但是它屬於一種盲目、機械的搜尋演算法,從3.5中的結果圖中可以看出,該演算法找出來的路徑,顯然不是最優的,走了許多的彎路。那麼如何從迷宮的起點到終點找到一條最優的路徑呢?請參考《迷宮問題求解之「a*搜尋」(二)》。
迷宮求解 窮舉求解法
迷宮求解是乙個理解資料結構中棧的比較好的實踐例子,下面進行分析 設迷宮是又乙個2維陣列組成的,元素只有0或1來表示是否通路,0代表通路,1代表有牆壁不通路 例如下圖中是一條通路 窮舉法 從入口出發,順某方向向前探索,如能走通,則繼續往前走,否則沿原路返回,換乙個方向再試,直到所有可能的銅鑼都探索到為...
回溯法求解迷宮問題
題目 這是我在老師發的ppt上發現的一道題,如下 1表示起點 7表示終點,一共六個路口,每個路口可以通達最多左上右三個路口,不能走的方向用0表示,求從1到7的路徑。求解思路 每個路口最多有三個搜尋分支。把演算法設計為如下的搜尋過程 把整個搜尋分解為向左 向前和向右三個方向上子問題的搜尋。當搜尋到某個...
回溯法求解迷宮問題
最近在leetcode上看了些演算法題,有些看著很簡單的很常用的東西,竟然一下子想不出來怎麼求解,比如說 實現sqrt函式,求陣列的排列。如果高數學的不好,這些看似簡單的問題,第一次碰到也會感覺很難求解,當然了,今天要說的是這樣乙個問題,求解迷宮的所有解,這個問題的求解用到了回溯法的思想,不了解這個...