資料結構::迷宮(二)--棧的一個應用(求迷宮最短路徑)
上篇文章我們知道求解迷宮通路的方法,但是一個迷宮有時是不止一條出路,在這些出路中,我們如何找到最短的那一條,這就是我今天要說的迷宮最短路徑問題。
(此處使用的圖):
【先來分析有什麼解決方案:】
1、方法一:我們如果採用上章中遞迴的方式,將所走的路用2標記起來,此時如果找到一條路後,要進行回溯遞迴,但是到可以走的環中就出現問題了,說的有點迷糊是吧,我把圖丟擲來。
在這張圖中我們可以看到,如果我們遞迴到又有一個可以走的路,就是圓圈2,那麼上面藍色線指的就走不回去了,因為已經走過了。所以這種方法是不可取的。有這方面的缺陷。
2、方法二:還是利用遞迴,但是我們做法不同
1)、每走一步標記的數值加1
2)、利用遞迴進行探測
3)、當找到一條路的時候,回溯遞迴
4)、此時,當探測的位置可以通的話,就繼續走,將下一位置標記數值加1
(為了防止回去,原則就是不能走比他數值小的位置)
【我們就採用第二種方案,來看怎麼實現】:
#include<iostream> #include<assert.h> #include<stack> using namespace std; #define N 10 //const size_t N = 10; //迷宮中所走的位置表示 struct Pos { /* size_t*/ int _row; //所在位置的行 /*sizt_t*/int _col; //所在位置的列 }; //獲取迷宮 void GetMaze(int* maze,size_t n) { FILE* fp = fopen("2.txt","r"); //先通過相對路徑開啟儲存迷宮地圖的文字 assert(fp); //開啟文字是否成功 for(size_t i = 0; i<n; i++) { for(size_t j = 0; j<n;) { int ret = fgetc(fp); if((ret == '0')|| (ret == '1')) { maze[i*n+j] = ret-'0'; //注意開啟的是文字要轉化成讀出的二進位制形式 j++; } //如果迷宮地圖本身不是n*n的,那麼上面的迴圈就會成為死迴圈 if(ret == EOF) { cout<<"出錯!"<<endl; } } } } //檢查此位置是否可以通 bool CheckIsAccess(int* maze,size_t n,Pos pos) { //首先這個位置得合法,其次再是pos這個位置是否為0 if(pos._row>=0 && pos._row<n && pos._col>=0 && pos._col<n && maze[pos._row*n+pos._col] == 0) { return true; } return false; } bool CheckIsAccess(int* maze,size_t n,Pos cur,Pos next) { //首先要走的這個位置得合法 if(next._row<=0 && next._row>n && next._col<=0 && next._col>n && maze[next._row*n+next._col] == 1) { return false; } //這個位置如果是0 if(maze[next._row*n+next._col] == 0) { return true; } //下一個位置要大於上一個位置加1(原則) if(maze[next._row*n+next._col] > maze[cur._row*n+next._col]+1) { return true; } return false; } //求解迷宮路徑 void GetMazePath_r(int* maze,size_t n,Pos entry,stack<Pos>& path,stack<Pos>& shortpath) { assert(maze); path.push(entry); Pos cur; Pos next; cur = entry; maze[cur._row*n+cur._col] = 2; //把走過的這個位置進行標記 next = cur; if(next._row == n-1) //找到了一條路 { if(shortpath.empty() || path.size()<shortpath.size()) { shortpath = path; } path.pop(); //下面加了return,所以要先進行pop一次,不然出來的結果就會多一個點(讀者可自行驗證下) return ; } //開始對上下左右進行探測 //對上的探測 next = cur; next._row -= 1; //檢查路是否可以通 if(CheckIsAccess(maze,n,cur,next)) { maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1; GetMazePath_r(maze,n,next,path,shortpath); } //對下的探測 next = cur; next._row += 1; //檢查路是否可以通 if(CheckIsAccess(maze,n,cur,next)) { maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1; GetMazePath_r(maze,n,next,path,shortpath); } //對左的探測 next = cur; next._col -= 1; //檢查路是否可以通 if(CheckIsAccess(maze,n,cur,next)) { maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1; GetMazePath_r(maze,n,next,path,shortpath); } //對右的探測 next = cur; next._col += 1; //檢查路是否可以通 if(CheckIsAccess(maze,n,cur,next)) { maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1; GetMazePath_r(maze,n,next,path,shortpath); } //到這個位置,說明四個方向都走不通,進行回溯 path.pop(); } //列印迷宮 void Print(int* maze, size_t n) { for(size_t i = 0; i<n; i++) { for(size_t j = 0; j<n; j++) { cout<<maze[i*n+j]; } cout<<endl; } } int main() { int maze[N][N]; stack<Pos> path; Pos entry = {2,1}; stack<Pos> shortpath; //輸出迷宮 GetMaze((int*)maze,N); GetMazePath_r((int*) maze,N,entry,path,shortpath); Print((int*) maze,N); cout<<"是否找到迷宮:"<<!path.empty()<<endl; return 0; }
說了這麼多,機智的你應該掌握了吧。
相關推薦
資料結構::迷宮(二)--棧的一個應用(求迷宮最短路徑)
上篇文章我們知道求解迷宮通路的方法,但是一個迷宮有時是不止一條出路,在這些出路中,我們如何找到最短的那一條,這就是我今天要說的迷宮最短路徑問題。 (此處使用的圖): 【先來分析有什麼解決方案:】 1、方法一:我們如果採用上章中遞迴的方式,將所走的路用2標記起來
資料結構實驗之二叉樹八:(中序後序)求二叉樹的深度(SDUT 2804)
#include <stdio.h> #include <stdlib.h> #include <string.h> struct node { char data ; struct node *l,*r; }; struct node *cr
資料結構實驗之二叉樹四:(先序中序)還原二叉樹 (SDUT 3343)
#include <bits/stdc++.h> using namespace std; struct node { char data; struct node *lc, *rc; }; char a[100],b[100]; int n; struct node
資料結構實驗之二叉樹四:(先序中序)還原二叉樹
Problem Description 給定一棵二叉樹的先序遍歷序列和中序遍歷序列,要求計算該二叉樹的高度。 Input 輸入資料有多組,每組資料第一行輸入1個正整數N(1 <= N <=
資料結構實驗之二叉樹八:(中序後序)求二叉樹的深度
Problem Description 已知一顆二叉樹的中序遍歷序列和後序遍歷序列,求二叉樹的深度。 Input 輸入資料有多組,輸入T,代表有T組資料。每組資料包括兩個長度小於50的字串,第一個字串表示二叉樹的中序遍歷,第二個表示二叉樹的後序遍歷。 Output
2804 資料結構實驗之二叉樹八:(中序後序)求二叉樹的深度
#include<iostream> #include <malloc.h> #include<string.h> using namespace std; struct node { char data;
用棧解決迷宮問題(輸出所有路徑和最短路徑)
#include<iostream> #include<cstdio> using namespace std; #define M 4 //行數 #define N 4 //列數 #define MaxSize 100 //棧最多元素個數 int m
迪傑斯特拉演算法(可列印最短路徑)(資料結構題集C語言版7.11)
轉自 https://blog.csdn.net/cxllyg/article/details/7604812 #include <iostream> #include <iomanip> #include <string> usi
HPU暑期第五次積分賽 - G-迷宮(BFS+最短路徑)
題目 程式碼 #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; int mp[110][11
Dijkstra(從一個源點到其他各點的最短路徑)
#include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 typedef struct { int vertex[MAXSIZE]; int edges[MAXSIZE][MAXSIZE]; }Gra
《資料結構與演算法》之棧的應用
1、字串的翻轉(逆序) 根據棧“後進先出”的特點,可以利用棧對字串進行反轉,即實現字串的逆序。 藉助於《資料結構與演算法》之棧(2)中的棧結構,相應實現的程式碼如下: public static void ReverString() { BigStack stac
一個例子讓你明白一個演算法-Dijkstra(求源點到各頂點最短路徑)
演算法思想 1.在一個圖中,把所有頂點分為兩個集合P,Q(P為最短路徑集合,Q為待選集合),用dis陣列儲存源點到各個頂點的最短路徑(到自身為0)。 2.初始化P集合,就是加入源點到該集合,並在ma
Dijkstra演算法(一個節點到其他所有節點的最短路徑)
Dijkstra(迪傑斯特拉)演算法是典型的單源最短路徑演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。Dijkstra演算法是很有代表性的最短路徑演算法,在很多專業課程中都作為基本內容有詳細的介紹,如資料
poj 3984迷宮問題(bfs求最短路徑 類似並查集儲存上個節點 儲存最短路徑)
迷宮問題 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16343 Accepted: 9762 Description 定義一個二維陣列: int maze[5][5] = { 0,
資料結構之迴圈佇列和棧的應用
前面提到,在佇列的順序儲存結構中,必須要討論順序佇列的陣列越界(或上溢)問題。 根據順序佇列的定義,我們可以很輕鬆的發現,當佇列刪除一個元素之後,即front指標向後移動之時,往往這個時候就有可能出現
[資料結構與演算法] 5,棧的應用-四則運算表示式求值
1,字尾(逆波蘭)表示法定義 計算器可以幫忙計算一些簡單的加減乘除,但是如果遇到一些比較複雜的,比如說有大中小括號的四則運算,那麼一些普通的計算器就無法實現運算了,但是觀察發現,所有的括號都是成對出
資料結構java語言實現之棧及其應用
棧的結構比較簡單,跟連結串列差不多底層還是一個數組,程式碼實現也比較容易,主要利用的就是他的先進後出的特點,java程式碼如下: <span style="font-size:14px;">package Stack; /* * 棧的實現 * 基本思路還是
仙島求藥(BFS迷宮尋找最短路徑)
描述 少年李逍遙的嬸嬸病了,王小虎介紹他去一趟仙靈島,向仙女姐姐要仙丹救嬸嬸。叛逆但孝順的李逍遙闖進了仙靈島,克服了千險萬難來到島的中心,發現仙藥擺在了迷陣的深處。迷陣由M×N個方格組成,有的方格內
UVa 1599 理想路徑(反向BFS 求最短路徑 )
ack pan clu inf struct name esp turn pop 題意: 給定一個有重邊有自環的無向圖,n個點(2 <= n <= 100000), m條邊(1 <= m <= 200000), 每條邊有一個權值, 求從第一個點到n的
hdu 2544(最短路徑)
cst cstring while span code 最短路徑 bre sha nbsp 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #inclu