1. 程式人生 > >尋找最短迷宮路徑/電路佈線問題(C++描述)

尋找最短迷宮路徑/電路佈線問題(C++描述)

基本思想和尋找迷宮路徑一致 https://mp.csdn.net/postedit/81980772 只是本文中找的是最短的路徑,而這一思想也經常用於電路佈線。主要方法是深度優先搜尋和回溯法。

基本的方法是從起始點開始,對其 上,右,下,左四個方向的位置進行距離標定,如果在某一方向上沒有障礙物則標定此方向距離起始點的距離,並且將此方向的位置放入佇列等待下次從此位置繼續開始標定。當然如果有障礙物則不標定。我們可以知道標識是否有障礙物的矩陣map還肩負著標識距離的重任,當然為了和1不發生衝突,距離值多加了2,這樣很巧妙的利用了標識陣列來標定距離,避免了重新開闢記憶體節省了記憶體。

從終點開始回溯,回溯的依據就是距離和標識點是差2的關係,其實這種關係從起始位置的設立map[start.first][start.second] = 2;就已經形成了。

程式碼如下:

#include<iostream>
#include<queue>
#include<vector>
#include<utility>
using namespace std;
bool findPath(vector<vector<int>>& mapIn,pair<int,int>& start,pair<int,int>& finish,vector<pair<int,int>>& path)
{
	if (mapIn.empty()) {
		return false;
	}
	int pathLength;
	if (start.first == finish.first&&start.second == finish.second){
		pathLength = 0;
		return true;
	}
	//方向設定
	vector<pair<int, int>> offset = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//分別代表右,下,左,上四個方向
    //初始化迷宮外面的障礙牆,這是為了處理邊界位置時比較方便
	int n = mapIn.size();
	vector<int> vtemp(n + 2, 1);
	vector<vector<int>> map(n + 2, vtemp);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{//把之前的障礙搬到新的地圖中
			map[i][j] = mapIn[i - 1][j - 1];
		}
	pair<int, int> here=start;
	map[start.first][start.second] = 2;  //1表示障礙,0表示可以通過,大於1表示相距起始點的距離(0+2)
	int numOfNbrs=4;
	//對可達到的位置做標記
	queue<pair<int, int>> q;
	pair<int, int> nbr;
	do {
		for (int i = 0; i < numOfNbrs; i++) {
			nbr.first = here.first + offset[i].first;
			nbr.second = here.second + offset[i].second;
			if (map[nbr.first][nbr.second] == 0) {//對可標記的位置做標記
				map[nbr.first][nbr.second] = map[here.first][here.second] + 1;
				if (nbr.first == finish.first&&nbr.second == finish.second) {//已經到達終點,結束
					break;
				}
				q.push(nbr);
			}
			
		}
		if (nbr.first == finish.first&&nbr.second == finish.second) {//已經到達終點,結束
			break;
		}
		//終點還沒到達,是否可以移到之前的第一個nbr
		if (q.empty()) {//沒有可以到達的路徑
			return false;
		}
		here = q.front();
		q.pop();
	} while (true);
	pathLength = map[finish.first][finish.second] - 2;//最短的距離
	cout << pathLength << endl;
	//回溯追蹤最短路徑經過的點
	path.clear();
	path.resize(pathLength);
	here = finish;   //從終點開始追蹤
	for (int j = pathLength - 1; j >= 0; j--)
	{
		path[j] = here;
		for (int i = 0; i < numOfNbrs; i++)
		{
			nbr.first = here.first + offset[i].first;
			nbr.second = here.second + offset[i].second;
			if (map[nbr.first][nbr.second] == j + 2) {
				break;//找到了滿足條件的位置,而且滿足條件的位置一定能找到
			}
		}
		here = nbr;//儲存,下次繼續從此點開始尋找
	}
	return true;
}
int main()
{
	vector<vector<int>> mapIn = { { 0,1,1,0,1,1 },
	                              { 0,0,1,0,1,0 },
	                              { 0,0,1,0,0,0 },
	                              { 1,0,0,0,1,0 },
	                              { 0,1,1,1,0,0 },
	                              { 0,1,1,1,0,0 } };
	pair<int, int> start(0,0);
	pair<int, int> finish(6, 6);
	vector<pair<int, int>> path;
	if (findPath(mapIn, start, finish, path)) {
		for (pair<int, int> pa : path)
		{//輸出經過的位置,包含終點,不含起始點
			cout << pa.first << " " << pa.second << endl;
		}
	}
	return 0;
}

相關推薦

尋找迷宮路徑/電路佈線問題C++描述

基本思想和尋找迷宮路徑一致 https://mp.csdn.net/postedit/81980772 只是本文中找的是最短的路徑,而這一思想也經常用於電路佈線。主要方法是深度優先搜尋和回溯法。 基本的方法是從起始點開始,對其 上,右,下,左四個方向的位置進行距離標定,如果

【BZOJ】4032: [HEOI2015]不公共子串LibreOJ #2123

後綴 blog clas 字母 小寫 算法 存在 識別 題意 【題意】給兩個小寫字母串A,B,請你計算: (1) A的一個最短的子串,它不是B的子串 (2) A的一個最短的子串,它不是B的子序列 (3) A的一個最短的子序列,它不是B的子串 (4) A的一個最短的子序列,它

作業優先排程演算法SJF演算法C++實現

題目要求: 在作業排程中,該演算法每次從後備作業佇列中挑選估計服務時間最短的一個或幾個作業,將他們調入記憶體,分配必要的資源,建立程序並放入就緒佇列。與在程序排程中的原理類似。假設有n項作業位於就緒佇

資料結構實現 6.2:優先佇列_基於大二叉堆實現C++版

資料結構實現 6.2:優先佇列_基於最大二叉堆實現(C++版) 1. 概念及基本框架 2. 基本操作程式實現 2.1 入隊操作 2.2 出隊操作 2.3 查詢操作 2.4 其他操作 3. 演算法複雜度分析

演算法題:長迴文子串C#實現

給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。 示例 1: 輸入: "babad" 輸出: "bab" 注意: "aba" 也是一個有效答案。 示例 2: 輸入: "cbbd" 輸出: "bb

PTA練習:小於m的大的10個素數C語言

給定一個整數m(50<m<20000),找出小於m的最大的10個素數。 輸入格式: 輸入在一行中給出一個正整數m(50<m<20000)。 輸出格式: 在一行中按遞減順序輸出10個滿足條件的素數,每個素數輸出佔6列。沒有其它任何附加格式和字元。

LeetCode第五題:長迴文子串C語言

給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。 示例 1: 輸入: “babad” 輸出: “bab” 注意: "aba"也是一個有效答案。 示例 2: 輸入: “cbbd” 輸出: “bb” 解法一:暴力求解法 思想:

動態規劃之長單調遞增子序列C++原始碼

動態規劃之最長單調遞增子序列 問題: L={a1,a2,a3,…,an}既L是由n個不同的實陣列成的序列,求L的最長單調遞增子序列(下標可不連續)。 分析: 設輔助陣列b,b[i]表示以a[i]為結尾的最長遞增子序列的長度,最長遞增子序列的長度,就是陣列b的最大

LeetCode 62. 不同路徑 Unique PathsC語言

題目描述: 一個機器人位於一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。 機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。 問總共有多少條不同的路徑? 例如,上圖是一個7 x 3 的網格。有多少可能的路徑

LeetCode 53. 大子序和 Maximum SubarrayC語言

題目描述: 給定一個整數陣列 nums ,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。 示例: 輸入: [-2,1,-3,4,-1,2,1,-5,4], 輸出: 6 解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。 進

排序演算法1:簡單的排序——桶排序C++版本

下面我要開始摘抄總結了。。。。文字來源於部落格2。。。 1.什麼是桶排序 桶排序,也叫做箱排序,是一種排序演算法,也是排序演算法中最快、最簡單的排序演算法。其中的思想是我們首先要知道所有待排序的範圍,然後需要有在這個範圍的同樣數量的桶,接

表示數值的字串C++描述

請實現一個函式用來判斷字串是否表示數值(包括整數和小數)。例如,字串"+100","5e2","-123","3.1416"和"-1E-16"都表示數值。 但是"12e","1a3.14","1.2.3

常用的數論演算法C++描述

網上找到的是PASCAL的……於是自己轉成C++來寫一遍…… 1.求兩數的最小公倍數和最大公約數 //(輾轉相除法/歐幾里德演算法)//求兩數的最大公約數int gcd(int a,int b)...{    if(b==0)        return a;    els

工廠方法模式C++描述

工廠方法模式是對簡單工廠模式的改進。首先看看簡單工廠模式的缺點。 軟體是之所以區別於程式,是因為它可以被人們使用,並能間接創造效益。需求是軟體開發的核心,忽視使用者的需求,軟體本身就沒有存在的價值。 假如Nokia又新開發了一款新手機N99,對於採用簡單工廠模式設計的系統,

線性表——順序表的實現與講解C++描述

線性表 引言 新生安排體檢,為了 便管理與統一資料,學校特地規定了排隊的方式,即按照學號排隊,誰在前誰在後,這都是規定好的,所以誰

雙鏈表的基本實現與講解C++描述

雙鏈表 雙鏈表的意義 單鏈表相對於順序表,確實在某些場景下解決了一些重要的問題,例如在需要插入或者刪除大量元素的時候,它並不需要

仙島求藥BFS迷宮尋找路徑

描述 少年李逍遙的嬸嬸病了,王小虎介紹他去一趟仙靈島,向仙女姐姐要仙丹救嬸嬸。叛逆但孝順的李逍遙闖進了仙靈島,克服了千險萬難來到島的中心,發現仙藥擺在了迷陣的深處。迷陣由M×N個方格組成,有的方格內

poj2251(bfs尋找路徑,三位迷宮)

題目連結:http://poj.org/problem?id=2251 Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K

尋找路徑

尋找 const 最短路徑 AI pac har spa AC utili #S######.# ......#..# .#.##.##.# .#........ ##.##.#### ....#....# .#######.#

dijkstra算法--尋找路徑

記錄 -h 兩個 In amp clas 通過 ant pan 轉自https://blog.csdn.net/heroacool/article/details/51014824 基本思想 通過Dijkstra計算圖G中的最短路徑時,需要指定起點s(即從頂點s開始計算