棧和佇列迷宮問題

2021-08-18 11:34:57 字數 3901 閱讀 4160

#define n 6

int maze[n][n] = 

, , 

, , 

, , 

}; 通過乙個數字來創造乙個6*6的迷宮,其中

0代表牆,

1代表能夠走的路。

這裡將陣列通過畫圖軟體畫出來,這裡紅色的1代表迷宮的入口,綠色的

1代表迷宮的出口。

這個陣列所建立的迷宮是相對複雜的一種迷宮,首先這個迷宮是存在環的

這幾個1,如果你的迷宮函式只是用簡單的迴圈程式來走或者說通過普通的遞迴那你就很有可能程式崩掉,陷入乙個死迴圈。

其次就是這個迷宮是存在兩條路的,通過兩條路可以出去,但是乙個長乙個短,應該通過什麼演算法才能找到那條短的路徑,這是乙個需要思考的問題。

最簡單的方法,如果這個迷宮不帶環的話,那完全可以通過遞迴來完成。

intcheckpath(

int*a,

posnext

, intn)

首先,通過乙個check函式來判斷你想要走的位置是否能走,如果是下乙個位置在迷宮陣列內並且數值為1那就代表著可以走。

intmazepath(

int*a,

intn

, pos

entry

)next = cur;

next._row++;

if(checkpath(

a, next, n))

next = cur;

next._row--;

if(checkpath(

a, next, n))

//同理  

next = cur;

next._col--;

if(checkpath(

a, next, n))

//同理  

return0;}

這是最基礎最簡單的尋找出口的方法,如果當前的值是四周任意一邊的乙個位置那就代表著找到了出口,函式就返回1,否則的話就開始通過遞迴不斷的往下走,這裡我首先是讓他往右如果不可以的話再走其他方向。這種方法走過的路程是不能回退的,也就是說你選擇一條路之後如果發現這條路不通想退回去是不能實現的。所以這個方法有很大的缺陷。

如果想要將走過的函式回退其實有很多辦法,當你所有都不能走的時候你可以走你之前走過的2的位置開始往回退,直到某個位置發現周圍有1,那你就可以去走那個1去換乙個路線來走,但是,其實想到回退大家很自然就能想到棧,你把你走過的路程每乙個位置都壓入到棧裡邊,如果不能走了那就從棧裡邊出乙個資料,也就是回退到上乙個位置,直到棧是空了,那就代表退到初始入口位置那就說明這個迷宮不存在通路。

while

(stackempty(s))

//若棧不為空  

a[cur._row*

n+ cur._col] = 2;

//將該位置置為2,代表已走過的路  

next = cur;

next._col++;

//若下乙個位置是當前位置的右邊  

if(checkpath(

a, next, n))

//若下乙個位置的值合法且為0(可以通),則跳到下乙個位置,且壓棧  

//若不可以通那麼就判斷令乙個方向的位置的值  

next = cur;

next._row++;

if(checkpath(

a, next, n))

//同理  

next = cur;

next._row--;

if(checkpath(

a, next, n))

//同理  

next = cur;

next._col--;

if(checkpath(

a, next, n))

//同理  

cur = stacktop(s);

//當四周都不可以通則回退,將當前位置置為棧頂元素的座標位置  

stackpop();

//頂元素彈出  

}這裡只需要在上邊函式中做乙個小改動,首先需要通過乙個迴圈來實現,迴圈的判斷條件就是棧s不為空,如果不為空還能走就一直走,如果遇到了四周位置那就直接返回。

if(checkpath(

a, next, n))

//同理  

這裡每到乙個位置,之後就把這個位置的資料入棧,然後跳過本次迴圈,因為如果不跳過的話,你某乙個位置好幾個方向能走,他就會將這幾個方向的位置全都存入棧中,跳出這次迴圈之後,會以剛剛入棧的這個當前位置為起點開始重新找他能夠走的方向,

cur = stacktop(s);

//當四周都不可以通則回退,將當前位置置為棧頂元素的座標位置  

stackpop();

//頂元素彈出  

如果某個位置判斷了上下左右全都不能走,不符合條件那就說明這條路線是一條死路,那就需要將棧頂的元素獲取出來也就是他的上乙個位置,重新開始走,那是不是會存在你從這邊退到上乙個位置,然後又從上乙個位置又走到當前位置的死迴圈呢?不會的,因為你每次走之前都會判斷下個位置能不能走,如果你經過了某個位置,你就會把這個位置的數值變成2,下次再往這個方向走的時候判斷條件就不成立。

通過棧來實現的話,當你走到出口的時候,還可以將棧的資料依次輸出出來,那就能獲得你所走過的路徑。

棧解決了乙個很大的問題,就是,你的當前路徑失敗的時候需要重新找到乙個岔路口,從哪個岔路口的另乙個方向開始走。但是現在還存在乙個問題就是,當你的迷宮存在兩條路的時候怎麼辦,如果你選擇了一條長的路徑就直接返回找到了路徑,該怎麼優化這個函式讓他能找到你的最短路徑。

這裡有人運用了很巧妙的方法,假如我上圖中畫的迷宮,在找路徑了找到了那個長的路徑,之前我將每個每個走過的位置都變成了2,這裡通過改進後的函式,是將你走過的每乙個位置的數值都在前乙個位置的基礎之上加1

所以如果是找遠的那個路徑的話,走過之後的陣列就會變成上圖的樣子,走的過程中,同樣是需要將所走過的每個位置的資料壓入棧之中,當你找到出口的時候,需要求一下當前棧中的資料個數,也就是你走過的位置的個數,就是你的路徑的長度。這時候開始往回退你的棧,還是去找數值為1的位置,

11附近沒有,

10附近沒有繼續退,到

9的時候發現左邊有乙個

1的元素,這時候把

1位置變成比

9大乙個的資料就是變成了

10。然後繼續走發現周圍沒有

1開始回退,到

9發現還是沒有

1繼續回退,一直退到

3的時候,發現

3的右邊這個元素要比他周圍其他元素要大,那就直接向右走

這是當前的情況,當開始從3開始走的時候,會往右走。這時候

10位置的資料變成了

4,然後繼續走

9位置的元素變成了

這時候5周圍有兩個元素,分別是8和

10,這和剛剛

3的選擇一樣,選擇周圍所有方向中大的那個資料走。

最後迷宮會變成這個樣子,這時並不知道迷宮的路徑已經被你遍歷完了,還是會開始回退,此時的棧中存的是紅色的路徑,開始回退,一直退到1 都沒發現周圍有能夠再走的

1元素,這時候說明所有路徑已經被找完了,直接返回剛剛存下的棧中的資料的個數就是你最短路徑的長度。

解決迷宮問題, 棧和佇列

includeusing namespace std const int m 10,n 10 int mg m 1 n 1 const maxsize 200 struct qu maxsize int front 1,rear 1 隊首指標和隊尾指標 1 首先將 1,1 入隊 2 在佇列qu不為空...

棧和佇列的迷宮問題

maze.h pragma once include include define n 6 static int maze n n typedef struct pos pos void mazeprint int mazegetpath pos entry,pos exit int mazeche...

棧,佇列實現迷宮問題

include includeusing namespace std int mg 10 10 入口 1,1 出口 8,8 typedef struct gezi typedef struct path void print path p,int pos while k 0 容易出錯,for int...