1. 程式人生 > >資料結構::迷宮(二)--棧的一個應用(求迷宮最短路徑)

資料結構::迷宮(二)--棧的一個應用(求迷宮最短路徑)

      上篇文章我們知道求解迷宮通路的方法,但是一個迷宮有時是不止一條出路,在這些出路中,我們如何找到最短的那一條,這就是我今天要說的迷宮最短路徑問題。

(此處使用的圖):


【先來分析有什麼解決方案:】

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