迷宮問題 壓棧 回溯 全部路徑 最短路徑

2021-08-20 13:56:05 字數 3903 閱讀 3867

用迴圈模擬壓棧來實現迷宮問題

arg.att:這個狀態用來標記我們是否試走過 此處 的四個方位,因為0是牆,1是路,所以我們用2來表示我們試過此處的左邊能不能通行,3用來表示此處的上方是否通行,4表示右邊,5表示下邊。用6來表示出口。假如說試過左邊不能走,我們就將標記改為3,讓他繼續試上邊能不能走。

進入迴圈之前,先將5,2以及初始標記值2壓進棧。

結束條件為,如果目標走到陣列右側,也就是gmaze[ ][n-1]結束,然後跳出整個迴圈。

(如果在這裡結束,我們則只能找到一條通路,我們讓while迴圈來決定是否結束,此時便能找出多個出口)

先看下面的此處座標各個方向能不能走,再看下面這段話:

然後我們檢視棧頂元素,也就是把當前的座標,以及此處的狀態複製到另乙個argnext中

先看左邊能不能走

如果argnext.att<=2說明是剛進來,還沒有試左邊能不能走,因此進入判左語句中

左邊能走我們,將陣列該位置的值改為2,並且列印這個陣列。

將argnext.x -= 1 後,判斷這個點是不是牆、否越界陣列,如果符合條件進入語句

進入語句就說明左邊是能走的通的,然後我們將棧頂的也就是arg的狀態arg.att改為3,說明我們已經走過左邊,並且能走,

改過當前位置的狀態之後,因為此處的左方是能走通的。因此我們需要將左方的座標以及初始狀態也壓入棧內,

左邊能走了,因為下面還有試其他方向的語句,我們讓它每次只走一條路,因此我們需要continue來跳出本次迴圈,假如沒有continue可能會使程式出錯。

試過左邊之後,試上邊能不能走

如果argnext.att<=3說明是已經試過左邊,然後來試上邊。

上邊能走我們,將陣列該位置的值改為3,並且列印這個陣列。

將argnext.y -= 1 後,判斷這個點是不是牆、否越界陣列,如果符合條件進入語句

進入語句就說明上邊是能走的通的,然後我們將棧頂的也就是arg的狀態arg.att改為4,說明我們已經走過上邊,並且能走,

改過當前位置的狀態之後,因為此處的上方是能走通的。因此我們需要將上方的座標以及初始狀態也壓入棧內。然後跳出本次迴圈。

試過上邊之後,試右邊能不能走

如果argnext.att<=4說明是已經試過上邊,然後來試右邊。

右邊能走我們,將陣列該位置的值改為4,並且列印這個陣列。

將argnext.y += 1 後,判斷這個點是不是牆、否越界陣列,如果符合條件進入語句

進入語句就說明右邊是能走的通的,然後我們將棧頂的也就是arg的狀態arg.att改為5,說明我們已經走過右邊,並且能走,

改過當前位置的狀態之後,因為此處的右方是能走通的。因此我們需要將上方的座標以及初始狀態也壓入棧內。然後跳出本次迴圈。

試過右邊之後,試下邊能不能走

如果argnext.att<=5說明是已經試過右邊,然後來試下邊。

右邊能走我們,將陣列該位置的值改為5,並且列印這個陣列。

將argnext.x += 1 後,判斷這個點是不是牆、否越界陣列,如果符合條件進入語句

進入語句就說明下邊是能走的通的,然後我們將棧頂的也就是arg的狀態arg.att改為6,說明我們已經走過下邊,並且能走,

改過當前位置的狀態之後,因為此處的下方是能走通的。因此我們需要將上方的座標以及初始狀態也壓入棧內。然後跳出本次迴圈。

這樣構成乙個迴圈,結束條件為棧為空,結束條件為棧為空時,我們可以尋找迷宮的多個出口。

每次在迴圈中列印陣列時,我門用乙個system(「cls」);來清屏,實現乙個看起來像是能動的迷宮(哈哈哈)

#pragma once

#include

#include

#include

#include

#include

#define max_ 100

#define row 6

#define col 6

//座標結構體

typedef

struct pos

pos;

//座標,當前位置狀態

typedef

struct arg

arg;

//棧typedef

struct stack

stack;

void print();

stack stack;

//迷宮

int gmaze[row][col] = ,,,

,,};//儲存每次路徑的指標陣列

int *gsuccess[row*col];

int gsize = 0;

//儲存最短路徑的指標

int *min = null;

int k = 0;

//定義乙個符號陣列來代替迷宮的1,2,3,4,5,6,

//看起來能直觀一點

static

const

char *symbols = ;

//初始化棧

void init(stack *stack)

//壓棧

void push(stack *stack, arg arg, int att)

//出棧

void pop(stack *stack)

//初始化

void destroy(stack *stack)

//棧大小

int size(stack *stack)

//棧是否為空

int isempty(stack *stack)

//棧頂元素

arg top(stack *stack)

//此位置是否通行

int checkisaccess(int x, int y)

else

}//清屏,並且改變陣列值為當前位置狀態

void setandprint(int x,int y, int att)

//改變棧內,當前座標狀態

void updatetop(stack *stack, int data)

//列印

void print(int (*gmaze)[col])

printf("\n");

}}//主迴圈體

void gomazerecirsion(pos pos)

}argnext = arg;

//左邊能不能走

if (argnext.att <= 2)

}//上邊能不能走

if (argnext.att <= 3)

}//右邊能不能走

if (argnext.att <= 4)

}//下邊能不能走

if (argnext.att <= 5)

}gmaze[arg.pos.x][arg.pos.y] = 1;

pop(&stack);

}printf("沒有通路了\n");

}//主函式體

void test()

; gomazerecirsion(pos);

printf("有%d種方法\n",gsize);

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

printf("最短路徑\n");

print((int(*)[col])min);

//別忘記釋放記憶體

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

free(min);

min = null;

gsuccess[gsize] = null;

system("pause");

}

#include "migong.h"

//主函式

用棧 求迷宮問題(最短路徑和全部路徑)

這是資料結構的作業,便找書邊看網上,然後自己慢慢寫出來的,這裡面主要是回溯法。因為課本上是列印出一條路徑,然後我在想怎樣能將所有的路徑都輸出來,方法 就是當求出一條路徑後,將出口點變成可以走的點 因為之前將其值變成了 1 並且將棧頂元素出棧,還需要得到現在棧頂元素的i,j,di值,將其賦出來。這裡的...

回溯法找迷宮最短路徑

有乙個二維陣列,0表示路,1表示牆,求其中任意兩點的最短路徑 我們先看,怎麼求一條路徑 求兩點路徑是乙個資料結構上的典型的迷宮問題,解決辦法如下 從一點開始出發,向四個方向查詢 上,右,下,左 每走一步,把走過的點的值 1,防止重複行走,並把走過的點壓入堆疊 表示路徑 如果遇到牆 或者已走過的點則不...

迷宮最短路徑問題

問題描述 給定乙個迷宮和乙個起點乙個終點,求起點到終點的最短路徑長度。sample input 說明 5行5列的迷宮,為牆,為路,起點為 0,3 終點為 4,4 sample output 若不可達輸出 1 解答 用bfs的方法,借助乙個佇列實現。1 include2 include3 includ...