求解迷宫最短路径
1. 多通路迷宮初始化
????先構(gòu)建一個(gè)多通路迷宮,并且對(duì)其初始化
void MazeInitShortPath(Maze* maze) {if(maze == NULL){return;}int row = 0;int col = 0;for(; row < MAX_COL; row++){for(col = 0; col < MAX_COL; col++){maze -> map[row][col] = Map[row][col];}printf("\n");} }????????????????????????
2. 定義一個(gè)棧并且打印
/** * @brief* * @用來(lái)測(cè)試迷宮棧* @param msg */ void SeqStackDebugPrint(SeqStack* short_path, char* msg) {printf("[%s]\n", msg);if(short_path == NULL || msg == NULL){return;}int i =0;for(;i < short_path -> size; i++){printf("(%d, %d)\n", short_path -> data[i].row, short_path -> data[i].col);}printf("\n"); }3. 遞歸找通路
????在次過(guò)程中, 用到的思路和上一篇的迷宮求通路的思路一樣. 即就是利用遞歸的方式實(shí)現(xiàn).不過(guò)因?yàn)榇舜斡泻枚鄠€(gè)出口, 所以我們每次都需要定義兩個(gè)棧, 保存當(dāng)前路徑, 以及最短路徑, 最后將最短路徑中的內(nèi)容打印出來(lái).首先, 先判斷當(dāng)前點(diǎn)是否可以落腳, 如果不能落腳, 就直接退出, 如果可以落腳, 就現(xiàn)將當(dāng)前位置標(biāo)記, 然后將其入棧, 再判斷當(dāng)前位置是否是出口, 如果是出口就得判斷當(dāng)前棧和最短路徑棧中它們兩個(gè)哪個(gè)路徑短, 如果當(dāng)前路徑比最短路徑的步數(shù)少, 或者最短;路徑棧為空, 就用當(dāng)前棧代替保存最短路徑的那個(gè)棧, 同時(shí)需要進(jìn)行回溯, 將保存當(dāng)前路徑的棧出棧.如果當(dāng)前位置不是出口, 就對(duì)當(dāng)前位置周圍的四個(gè)位置進(jìn)行探索,直到找到出口為止. 如果當(dāng)前位置周圍的四個(gè)點(diǎn)都已經(jīng)探索, 此時(shí)就需要回溯了, 回溯的過(guò)程中也需要將保存當(dāng)前位置的棧的元素出棧.
//輔助遞歸 void _GetShortPath(Maze* maze, Point cur, Point entry, SeqStack* cur_path, SeqStack* short_path) {if(maze == NULL){return;}printf("(%d, %d)\n", cur.row, cur.col);//1. 判斷當(dāng)前是否可以落腳if(CanStay(maze, cur) == 0){return;}//2. 能落腳就將其標(biāo)記, 插入到cur_pathMark(maze, cur);SeqStackPush(cur_path, cur);//3. 判定當(dāng)前是否是出口//b) 如果當(dāng)前路徑?jīng)]有short_path短, 就回溯找其他路徑, 在回溯前也需要將 cur_path 出棧if(IsExit(maze, cur, entry)){printf("找到了一條較短的路\n");if(cur_path -> size < short_path -> size || short_path -> size == 0){//a) 如果是出口, 說(shuō)明找到了一條路, 拿著當(dāng)路徑和short_path 比較, 如果當(dāng)前路徑比 short_path 路徑短, //應(yīng)當(dāng)前路徑代替 short_path(打擂臺(tái)), 或者 short_path 是個(gè)空棧, 就用當(dāng)前棧代替short_path, 代替完//需要回溯, 找其他路徑SeqStackAssgin(short_path, cur_path);}SeqStackPop(cur_path);return;}//4. 當(dāng)前點(diǎn)不是出口, 嘗試找四個(gè)方向(探測(cè)四個(gè)方向)Point up = cur;up.row -= 1;_GetShortPath(maze, up, entry, cur_path, short_path);Point right = cur;right.col += 1;_GetShortPath(maze, right, entry, cur_path, short_path);Point down = cur;down.row += 1;_GetShortPath(maze, down, entry, cur_path, short_path);Point left = cur;left.col -= 1;_GetShortPath(maze, left, entry, cur_path, short_path);//5. 如果四個(gè)方向都探測(cè)過(guò)了, 回溯返回到上一個(gè)點(diǎn), 同時(shí) cur_path 出棧 SeqStackPop(cur_path); } void GetShortPath(Maze* maze, Point entry) {if(maze == NULL){return;}if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL){return;}SeqStack cur_path;SeqStack short_path;SeqStackInit(&cur_path);SeqStackInit(&short_path);_GetShortPath(maze, entry, entry, &cur_path, &short_path);SeqStackDebugPrint(&short_path, "打印棧內(nèi)容");printf("%d\n", short_path.size); }4. 棧的復(fù)制
????為了代碼實(shí)現(xiàn)的簡(jiǎn)單, 我們定義兩個(gè)棧, from, to, from比to的元素要少. 在復(fù)制之前, 將to 的內(nèi)存先進(jìn)行釋放, 然后對(duì)to進(jìn)行動(dòng)態(tài)內(nèi)存分配, 接著將 from 結(jié)構(gòu)體的所有信息全部復(fù)制到 to 中,最后將from中的元素依次復(fù)制給 to即可
void SeqStackAssgin(SeqStack* to, SeqStack* from) {if(from == NULL || to == NULL){return;}SeqStackDestroy(to);to -> data = (Point*)malloc(from -> capacity * sizeof(SeqStackType));to -> size = from -> size;int i = 0;for(; i < from -> size; i++){to -> data[i] = from -> data[i];} }????????????????????????
????????????????????????
5. 總結(jié)
????總結(jié)一下, 整體思路如下. 先定義兩個(gè)棧 cur_path , shrott_path, 前者保存當(dāng)前路徑.后者保存最短路徑, 接著 判斷當(dāng)前位置是否可以落腳, 如果不能落腳就直接返回, 如果可以落腳就將當(dāng)前位置標(biāo)記, 然后將當(dāng)前點(diǎn)進(jìn)行入棧, 入棧到 cur_path中, 接下來(lái)判斷當(dāng)前位置是否為出口, 如果是出口, 就比較 cur_path 和 short_path 之間的長(zhǎng)度, 如果 cur_path的元素少于 short_path 的元素或者 short_path 為空, 就用cur_path 代替 short_path, 然后將當(dāng)前 cur_path 棧出棧, 接著進(jìn)行回溯. 如果當(dāng)前棧的元素個(gè)數(shù)大于 short_path棧的元素, 就將 cur_path 出棧, 然后進(jìn)行回溯; 如果當(dāng)前位置不是出口, 就按照順序(順時(shí)針)探測(cè)當(dāng)前位置周圍的四個(gè)點(diǎn), 如果當(dāng)前位置周圍的四個(gè)點(diǎn)都已經(jīng)探測(cè), 此時(shí)說(shuō)明進(jìn)入了死胡同, 就需要回溯, 回溯之前不要忘記將當(dāng)前的棧 cur_path 進(jìn)行出棧, 最后,當(dāng)遞歸結(jié)束時(shí), 打印 short_path棧, 因?yàn)樵摋@锉4娴木褪亲疃搪窂?/p>
總結(jié)
- 上一篇: 死锁的产生和避免
- 下一篇: 成都欢乐谷现在门票多少钱