非遞迴求解迷宮所有路徑問題遇到的BUG

2021-10-01 14:14:59 字數 2461 閱讀 3906

不知道有沒有人和我一樣,在用棧求解迷宮問題所有可行解得時候,會遇到相同路徑重複輸出的bug。我看了網上問其他部落格的**,發現也有這個bug,功夫不負有心人,花了1小時之久終於發現了bug!

bug如下圖:

上的路徑1,2重複了,路徑4,5重複了,除去重複路徑,真實的路徑只有4條。接下來展示排錯前的**,也是出現上述問題大部分人的**。

#include

#include

#include

//計時器,計算**運算時間

#define inf 100

//初始化最小路徑長度

const int maxsize=

1000

;//棧的大小

int m=8

,n=8

;//初始化迷宮,1代表障礙,0代表可通過。

int mg[10

][10]

=,,,

,,,,

,,};

typedef struct

box;

typedef struct

sqstack;

//順序棧型別

void

initstack

(sqstack *

&s)//初始化棧

bool push

(sqstack *

&s,box e)

//進棧

bool stackempty

(sqstack *s)

//判斷棧是否為空

bool pop

(sqstack *

&s,box &e)

//出棧

bool gettop

(sqstack *s,box &e)

//取出棧頂元素

bool mgpath

(int xi,int yi,int xe,int ye)

//(xi,yi)是您迷宮的起點,(xe,ye)是終點。

printf

("迷宮路徑%d為:\n"

,cont++);

for(k=

0;k<=st-

>top;k++

)printf

("(%d,%d)\t"

,st-

>data[k]

.i,st-

>data[k]

.j);

printf

("\n");

pop(st,e);mg

[e.i]

[e.j]=0

;}elseif(

mg[i1]

[j1]==0

) _find=

true;}

if(_find)

else}}

if(f==1)

return

false;}

int main()

上述**按邏輯來說是沒問題的,當到探索達終點時,則從棧底到棧頂輸出該路徑上的所有結點。

這段**有bug的直接原因:本該出棧的方塊未及時出棧。bug就在當某個方格的4個方向都已經探索過,判斷是否出棧的語句中。而出棧方塊與否與變數_find直接相關。

在上述**中,我們不妨設想一下,假如某個方塊的四個方向均已探索過,find變數是否一定是false。回答是否定的,因為當某個方塊di已經為3時仍能進入下圖所示**一次,di++後,di已經變成了4。但在switch中沒有di==4的情況,所以對應的 i1, j1有滯後性,會等於上乙個已經出棧的方塊在迷宮中的值,也就是0,所以find仍為true,本該出棧卻沒有出棧,所以會有相同路徑重複輸出。

所以只要在判斷_find為true or false的判斷條件上再加上一句"di<=3"的判定條件,就可以解決上述bug。

//改正前

while(di<4&&!_find)

if(mg[i1][j1]==0) _find=true;

}//修正後

while(di<4&&!_find)

if(mg[i1][j1]==0 && di<=3) _find=true;

}

我想大家之所以會想選擇用棧非遞迴求解迷宮問題,是因為一句話「能用迴圈解決的就不用遞迴。」雖然遞迴有結構簡單、清晰,易於閱讀,方便其正確性證明的優點。但是占用記憶體過多,執行效率低,不易優化也是不容忽視的。

但是幾乎所有的排序的高效演算法都是採用了遞迴的分治思想,如二分歸併排序、快速排序和堆排序。所以說,處理相同問題,迴圈一定比遞迴好的說法是錯的。於是我對比了用遞迴做迷宮問題和用棧做迷宮問題的時間開銷發現兩者的時間開銷是大致相同的。但是在漢諾塔問題中,移動10個碟片,我發現用棧比用遞迴做快了將近10000倍。而且隨著規模增大,效率的高低懸殊更加明顯。

求解迷宮問題的所有路徑及最短路徑程式

路障 路障路障 路障路障 路障路障 入口 路障路障路障 路障 路障路障 路障路障路障路障 出口 路障路障 路障路障 路障路障 路障如上圖,要求輸出迷宮的所有路徑,並求出最短路徑長度及最短路徑。入口座標設為 1,1 出口座標設為 4,4 親,接下來 include define m 4 行數 defi...

老鼠走迷宮問題,求出所有路徑

本次所練習使用的主要方法是遞迴 所要注意的主要問題是 要確定起訖點的相對位置,否則又由於遞迴 的順序會漏掉一些可行路徑 先橫向 縱向接近目標點,然後再橫向 縱向遠離目標點 最好對應 例如 假設訪問的順序是下上右左 相對於乙個固定的矩陣 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 ...

用棧求解迷宮問題的所有路徑及最短路徑程式

目的 掌握棧在求解迷宮問題中的應用。內容 編寫乙個程式,輸出迷宮的所有路徑,並求第一條最短路徑長度及最短路徑。如下 include include include include using namespace std define inf 0x3f3f3f const int maxsize 10...