利用堆疊實現迷宮問題的求解

2021-06-22 08:43:06 字數 3518 閱讀 4091

解決迷宮問題的常用演算法就是回溯法,基本思想就是:從起點出發,順著乙個方向探索,若能夠走通,則繼續往前走,若不能夠走通,則沿原路退回一步,換乙個方向繼續探索,直至找到乙個可行的通路。此時從可行通路的到達終點的前一步進行回溯,即先從終點退一步到達終點前的第乙個位置,若該位置的四個方向還沒有探索完,則換乙個方向繼續探索,若四個方向均探索完,則再退一步到達終點前的第二個位置,若該位置的四個方向還沒有探索完,則換乙個方向繼續探索,若四個方向均探索完,則再退一步到達終點前的第三個位置,如此判斷下去直至起點的四個方向都探索完,則所有的解也就找到了。

需要注意的地方是很多同學一上手就開始進行回溯演算法的設計而忽略了迷宮可能存在的兩種不同的情況:

1、起點和終點不相同,此時得到的路線應該是一條折線。

2、起點和終點形同,此時得到的路線應該是乙個閉合的環路。

(1)要考慮如何避免把起點壓入棧之後,誤把迷宮起始位置當作是終點位置而沒有進行路徑的查詢直接就以為找到了一條路徑的情況。

(2)還要考慮如何避免出現起點->起點的(上、下、左、右)->終(起)點,這種非閉合環路的情況。

我們將迷宮中走過的位置壓入桟中,當找到一條路徑時,從桟底到棧頂就是迷宮的一條通路。

為了表明迷宮的各個位置是否可以通過,是否在桟中以及它的四個方向的遍歷情況,我們設定乙個標誌陣列,其含義如下:

typedef structflag;

flag cellarray[ row ][ col ]; 

對每個位置的四個方向的遍歷我們總是從東(1)開始以北(4)結束。

從起點出發,將起點入棧,並將其對應的標誌陣列的direction項設定為1,向東進行探索,若能夠走通,則繼續往東走,若不能夠走通,則沿原路退回一步,向南繼續探索並將direction項設定為2,直至找到乙個可行的通路。此時桟底為起點,棧頂為終點,從桟底到棧頂形成了第一條迷宮的通路。開始回溯:先將終點從桟中彈出,對棧頂的位置的標誌陣列的direction項進行判斷,若direction項還不為4表明該位置的四個方向還沒有探索完,則direction++換乙個方向繼續探索直至到達終點然後繼續從終點開始回溯或者從該位置沒有一條可以到達終點的通路,當direction項等於4說明該位置的所有方向都已經探索完畢,從該位置到終點的可能的通路都已經找到,則將該位置彈出桟,繼續對棧頂位置的direction進行判斷如此判斷下去直至起點的四個方向都探索完,則所有的解也就找到了。

//桟的資料結構
typedef	structlelemtype;

typedef struct templstack;

void main()

{ //陣列元素為1表示不能通過,即為牆壁,為0則可以通過

int mazearray[ row ][ col ] =,

, ,

, ,

};/* int mazearray[ row ][ col ] =,

, ,

, ,

, ,

, ,

};*/ lelemtype start;

lelemtype end;

int i,j;

for( i = 0; i < row; i++ )

//由於顯示長度有限,如果使用陣列形式列印,前面部分會看不到,因此為了看到全部路徑的輸出,可在mazepath函式中將列印陣列形式注釋掉

start.row = 1;

start.col = 1;

end.row = 3;

end.col = 3; //第乙個6*6陣列對應的迷宮的終點位置,用於測試起點和終點不同的情況

printf("end different form start:start[%d,%d]end[%d,%d]\n", start.row, start.col, end.row, end.col);

mazepath( mazearray, start, end );

end.row = 1; //第乙個6*6的陣列對應的迷宮的終點位置,用於測試起點和終點相同的情況,

end.col = 1;

printf("end equals start:start[%d,%d]end[%d,%d]\n", start.row, start.col, end.row, end.col);

mazepath( mazearray, start, end );

}

//乙個位置的東南西北表示為1,2,3,4

void mazepath( int maze[ row ][ col ], lelemtype start, lelemtype end )

flag;

flag cellarray[ row ][ col ]; //標誌位陣列

lstack *stack; //指向棧的頭元素

lelemtype curpos; //當前位置

lelemtype e;

int curstep = 0; //第curstep條通路

int i,j;

for( i = 0; i < row; i++ )

else

cellarray[i][j].instack = false; //初始化時所有的位置均不在棧中

} }stack = initstack( ); //初始化棧空間

curpos.row = start.row;

curpos.col = start.col;

do }

curstep += 1;

printf( "第%d條通路\n", curstep ); //由於鏈式棧的第乙個元素為棧頂,因此列印的結果應從後往前看

pathprint_array( stack ); //陣列形式列印路徑,為了看到所有路徑的輸出,可將該行注釋掉

pathprint_tuple( stack ); //二元組形式列印路徑

pop( stack, &e ); //每得到一條路徑,就將終點彈出棧,並將終點的instack設為0

cellarray[e.row ][e.col].instack = false;

gettop( stack, &curpos ); //把彈棧後的棧頂元素作為當前位置,重新開始迴圈(回溯)

continue;

}curpos.col = curpos.col + 1;//

} else

if( cellarray[e.row ][e.col].direction < 4 )

curpos.row = e.row;

curpos.col = e.col - 1;

}curpos.row = e.row - 1;

curpos.col = e.col;}}

} }while( !stackempty( stack ) );

destroystack( stack );

}

迷宮求解問題 堆疊的使用

queue.h define stack init size100 define stackincrement10 define statusbool define error0 define overflow 2 define ok1 struct postype typedef struct s...

利用棧實現迷宮求解

如下是每個節點的資料結構 1 typedef struct direction 方向 78 typedef struct point 位置 1213 14 typedef struct stacknode linkstackptr 節點資料結構 鏈棧及基本操作實現 1 typedef struct ...

利用棧求解迷宮問題

利用棧求解迷宮問題 源 include include define m 8 define n 8 define maxsize m n typedef struct box typedef struct sttype int mg m 2 n 2 bool mgpath int xi,int yi...