帶環迷宮求最短路徑

前面介紹了簡單的迷宮求解問題, 今天我們就對帶環迷宮求出它的最短路徑
1.首先來看一個帶環迷宮的簡單地圖

????????????????????????????????這里寫圖片描述
????在這張迷宮地圖中,我們規定入口點的位置entry的坐標是 (0, 1), 同時, 我們給入口點傳一個非法坐標,作為入口點的前一個位置(-1, -1). 接下來的思路就和上一篇的思路是一樣的的了. 即每次判斷當前點是否可以落腳, 如果不能落腳就直接退出, 如果可以落腳, 就將當前位置的點進行入棧操作, 將其標記(和前面不一樣了), 接著判斷當前點是否是出口, 如果是出口, 就將拿著 cur_path 和 short_path 進行比較, 將較短的保存在 short_path 中, 然后將 cur_path 出棧, 接著再進行回溯. 如果當前點不是出口, 就按照順序依次探測當前點周圍的四個點, 如果四個點都已經探測完了, 就需要回溯, 回溯的同時不要忘記將當前棧 cur_path 出棧

2. 判斷當前位置是否可以落腳

????判斷當前位置是否可以落腳可以分為以下兩種情況
????(1)當前位置還沒有走過
????此時地圖對應的二維數組的值是 1, 即這個位置一定可以落腳
????(2)當前位置如果已經走過, 我們需要借助當前位置的前一個落腳元素來判斷當前位置是否可以落腳, 當前一個位置在地圖上對應的值加1 小于當前位置在地圖上的值的時候, 此時證明該位置就可以落腳, 即 cur > pre + 1此時就可以落腳

int CanStayWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return 0;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return 0;}//當前位置是墻if(maze -> map[cur.row][cur.col] == 0){return 0;}//在取 prev 之前判斷 prev 是否合法if(prev.row == -1 && prev.col == -1){return 1;}//此時的prev 已經不再是入口點的前一個坐標if(prev.row < 0 || prev.row >= MAX_ROW || prev.col < 0 || prev.col >= MAX_COL){return 0;}//當前位置已經走過, 比較 cur 和 prev 的大小關系if(maze -> map[cur.row][cur.col] > maze -> map[prev.row][prev.col] + 1){return 1;}//如果當前點是 1 就直接可以落腳if(maze -> map[cur.row][cur.col] == 1){return 1;}return 0;
}
3. 對當前位置進行標記

????對當前位置標記分為兩種情況, 第一種就是看當前位置是否為入口, 如果是入口, 就將地圖對應的當前位置處的坐標變為2,否則就是讓 map[cur.row][cur.col] = map[prev.row][prev.col] + 1

void MarkShortPathWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return;}if(prev.row < -1 || prev.row >= MAX_ROW || prev.col < -1 || prev.col >= MAX_COL){return;}if(prev.row == -1 && prev.col == -1){maze -> map[cur.row][cur.col] = 2;return;}maze -> map[cur.row][cur.col] = maze -> map[prev.row][prev.col] + 1;return;
}
3. 迷宮求解遞歸代碼
int CanStayWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return 0;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return 0;}//當前位置是墻if(maze -> map[cur.row][cur.col] == 0){return 0;}//在取 prev 之前判斷 prev 是否合法if(prev.row == -1 && prev.col == -1){return 1;}//此時的prev 已經不再是入口點的前一個坐標if(prev.row < 0 || prev.row >= MAX_ROW || prev.col < 0 || prev.col >= MAX_COL){return 0;}//當前位置已經走過, 比較 cur 和 prev 的大小關系if(maze -> map[cur.row][cur.col] > maze -> map[prev.row][prev.col] + 1){return 1;}//如果當前點是 1 就直接可以落腳if(maze -> map[cur.row][cur.col] == 1){return 1;}return 0;
}void MarkShortPathWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return;}if(prev.row < -1 || prev.row >= MAX_ROW || prev.col < -1 || prev.col >= MAX_COL){return;}if(prev.row == -1 && prev.col == -1){maze -> map[cur.row][cur.col] = 2;return;}maze -> map[cur.row][cur.col] = maze -> map[prev.row][prev.col] + 1;return;
}void _GetShortPathWithCircle(Maze* maze, Point entry, Point cur, SeqStack* cur_path, SeqStack* short_path, Point prev)
{if(maze == NULL){return;}if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL){return;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return;}if(cur_path == NULL || short_path == NULL){return;}//1. 判定當前點是否可以落腳if(CanStayWithCircle(maze, cur, prev) == 0){return;}//2. 如果能落腳, 就標記當前點, 并將其入棧到 cur_path中MarkShortPathWithCircle(maze, cur, prev);SeqStackPush(cur_path, cur);//3. 判定當前是否是出口if(IsExit(maze, cur, entry))// a) 如果是出口, 就將 cur_path 和 short_path 比較, 把較短的路徑保存到 cur_path 中// 還有一種就是如果 short_path 的長度為 0, 就用 cur_path 代替 short_path ,然后將 cur_path// 出棧, 并且回溯{printf("找到了一條路\n");if(cur_path -> size < short_path -> size || short_path -> size == 0){SeqStackAssgin(short_path, cur_path);}SeqStackPop(cur_path);return;}// b) 如果不是出口, 以當前點為基準, 順時針探測 周圍四個點Point up = cur;up.row -= 1;_GetShortPathWithCircle(maze, entry, up, cur_path, short_path, cur);Point right = cur;right.col += 1;_GetShortPathWithCircle(maze, entry, right, cur_path, short_path, cur);Point down = cur;down.row += 1;_GetShortPathWithCircle(maze, entry, down, cur_path, short_path, cur);Point left = cur;left.col -= 1;_GetShortPathWithCircle(maze, entry, left, cur_path, short_path, cur);//4. 如果四個方向都探測過了, 回溯SeqStackPop(cur_path);return;
}void GetShortPathWithCircle(Maze* maze, Point entry, Point prev)
{if(maze == NULL){return;//非法輸入}if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL){return;//非法輸入}//規定第一個prev點的坐標是(-1, -1)if(prev.row != -1 && prev.col != -1){return;}//定義兩個棧SeqStack cur_path;SeqStack short_path;//分別對這兩個棧進行初始化SeqStackInit(&cur_path);SeqStackInit(&short_path);//輔助遞歸_GetShortPathWithCircle(maze, entry, entry, &cur_path, &short_path, prev);SeqStackDebugPrint(&short_path, "最短路徑");
}

????????????????????????????????這里寫圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384029.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384029.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384029.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

UVa1583

【題目描述】 傳送門 【題目分析】 我以為很簡單就寫了一個暴力沒有想到超時了。應該是T是非常大的所以必須得打表&#xff0c;將所有的結果都儲存起來然后直接輸出。 以后遇到這種可以一下算出所有結果的多組數據最好還是算出所有的結果然后再輸出答案。 【AC代碼】 #inc…

C 結構體嵌套一級指針 二級指針 動態分配內存

https://blog.csdn.net/xielinhua88/article/details/51364623 點擊打開鏈接 #define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> //結構體嵌套一級指針 二級指針 動態分配內存 typedef struct _Teacher { int ag…

線程的同步與互斥

1. 互斥量 在Linux 下線程使用的都是局部變量, 而我們知道, 每一個線程都獨立擁有自己的一個棧, 而這些局部便令就在棧中,而線程的創建就是為了實現通信, 此時線程之間無法共享這些變量 ????為了使得線程之間能夠共享數據, 一次我們可以創建一個全局變量, 此時線程都在進程…

二級指針與指針數組的關系

http://blog.csdn.net/shuaishuai80/article/details/6129742 #include <stdio.h> void test(char *argv[]); int main(void) { char *argv[3]{{"abcdefg"},{"1234567"},{"q1w2e3r"}}; test(argv); /*調用指針數組…

UVa1584

【題目描述】 傳送門 【題目分析】 也是一道簡單的模擬題&#xff0c;1A嘿嘿嘿。 再看書發現和書上的做法差不多。 【AC代碼】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstd…

cf#582div3 D——暴力

【題目描述】 The only difference between easy and hard versions is the number of elements in the array.You are given an array a consisting of n integers. In one move you can choose any ai and divide it by 2 rounding down (in other words, in one move you c…

C語言 可變參數

http://www.cnblogs.com/zhanggaofeng/p/6434554.html //可變參數 #include <stdio.h> #include <stdlib.h> #include <string.h> //引用頭文件 #include <stdarg.h>/* va_list用于聲明一個變量&#xff0c;我們知道函數的可變參數列表其實就是一個字符…

UVa1585

【題目描述】 傳送門 【題目分析】 氵 【AC代碼】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector>u…

c語言經典算法——查找一個整數數組中第二大數

https://www.cnblogs.com/dootoo/p/4473958.html 題目&#xff1a; 實現一個函數&#xff0c;查找一個整數數組中第二大數。 算法思想&#xff1a; 設置兩個變量max1和max2&#xff0c;用來保存最大數和第二大數&#xff0c;然后將數組剩余的數依次與這兩個數比較&#xff0c;如…

進程間關系和守護進程

一. 進程組/作業/會話 1.進程組 每一個進程除了有一個進程ID之外, 還屬于一個進程組. 進程是一個或多個進程的集合. 通常, 它們與同一個作業向關聯, 可以接收來自同一個終端下的各種命令,信號. 每一個進程組都有唯一的進程組 ID. 每一個進程組都可以有一個組長進程. 組長進程的…

UVa1586

【題目描述】 傳送門 【題目分析】 氵 【AC代碼】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector> …

猴子偷桃問題

http://blog.csdn.net/snow_5288/article/details/52561882 問題描述&#xff1a; /*有一群猴子&#xff0c;去摘了一堆桃子*/ /*商量之后決定每天吃剩余桃子的一半*/ /*當每天大家吃完桃子之后&#xff0c;有個貪心的小猴都會偷偷再吃一個桃子*/ /*按照這樣的方式猴子們每天都…

UVa1225

【題目描述】 傳送門 【題目分析】 做題做多了慢慢都忘記暴力了&#xff0c;想要快速算出來&#xff0c;找到規律&#xff0c;但是找來找去好復雜的都沒有找到&#xff0c;然后寫了一個不能再暴力的寫法&#xff0c;就過了。。。 我還是覺得如果數據范圍變成1e9那種級別的還…

linux 線程學習之條件變量

http://blog.csdn.net/hemmanhui/article/details/4417433 互斥鎖&#xff1a;用來上鎖。 條件變量&#xff1a;用來等待&#xff0c;當條件變量用來自動阻塞一個線程&#xff0c;直到某特殊情況發生為止。通常條件變量和互斥鎖同時使用。 函數介紹&#xff1a; 1&#xff0e;…

UVa455

【題目描述】 傳送門 【題目分析】 就是一個簡單的暴力&#xff0c;只是需要注意輸出格式比較毒瘤。 【AC代碼】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<cmath> #i…

網絡相關基礎概念

一. 相關基礎概念 1.計算機網絡的特點 (1)連通性:計算機網絡使得上網的用戶都能夠彼此相連, 好像用戶的計算機可以直接相連 ????(2)資源共享:資源共享可以是信息共享, 軟件共享, 硬件共享等等. 由于網絡的存在, 使得用戶感覺資源就在自己身邊 2. 網絡 網絡是由若干結點和…

linux線程同步(2)-條件變量

https://www.cnblogs.com/yuuyuu/p/5140875.html linux線程同步(2)-條件變量 一.概述 上一篇&#xff0c;介紹了互斥量。條件變量與互斥量不同&#xff0c;互斥量是防止多線程同時訪問共享的互斥變量來保護臨界區。條件變量…

UVa227

【題目描述】 傳送門 【題目分析】 題目的意思很簡單&#xff0c;只是輸入輸出很毒瘤&#xff0c;我一開始用的fgets然后用scanf(" ")吃掉所有的空格和換行&#xff0c;可是這樣有可能將迷宮的空格吃掉&#xff08;例如這個空格恰好在第一行第一列&#xff09;。 …

點對點數據鏈路層

數據鏈路層的主要功能將數據轉換為相應的比特流使用的信道主要有點對點的信道方式(一對一的方式), 以及廣播的信道方式 一. 點對點信道的數據鏈路層 1. 數據鏈路和數據幀 鏈路就是從一個結點連接到相鄰結點的一段物理線路(有線或者無線), 期間不準有任何的交換結點, 因此兩臺…

UVa232

[題目描述] 傳送門 [題目分析] 簡單的模擬,注意細節 [AC代碼] #include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype> #include<queue> #include<set>using namespace std;typedef long…