1. 程式人生 > >仙島求藥(BFS迷宮尋找最短路徑)

仙島求藥(BFS迷宮尋找最短路徑)

描述 少年李逍遙的嬸嬸病了,王小虎介紹他去一趟仙靈島,向仙女姐姐要仙丹救嬸嬸。叛逆但孝順的李逍遙闖進了仙靈島,克服了千險萬難來到島的中心,發現仙藥擺在了迷陣的深處。迷陣由M×N個方格組成,有的方格內有可以瞬秒李逍遙的怪物,而有的方格內則是安全。現在李逍遙想盡快找到仙藥,顯然他應避開有怪物的方格,並經過最少的方格,而且那裡會有神祕人物等待著他。現在要求你來幫助他實現這個目標。
下圖 顯示了一個迷陣的樣例及李逍遙找到仙藥的路線.

輸入 輸入有多組測試資料. 每組測試資料以兩個非零整數 M 和 N 開始,兩者均不大於20。M 表示迷陣行數, N 表示迷陣列數。接下來有 M 行, 每行包含N個字元,不同字元分別代表不同含義: 
1) ‘@’:少年李逍遙所在的位置;
2) ‘.’:可以安全通行的方格;
3) ‘#’:有怪物的方格;
4) ‘*’:仙藥所在位置。
當在一行中讀入的是兩個零時,表示輸入結束。
輸出 對於每組測試資料,分別輸出一行,該行包含李逍遙找到仙藥需要穿過的最少的方格數目(計數包括初始位置的方塊)。如果他不可能找到仙藥, 則輸出 -1。 樣例輸入
8 8
[email protected]
##...# #....#.# #.#.##.. ..#.###. #.#...#. ..###.#. ...#.*.. .#...### 6 5 .*.#. .#... ..##. ..... .#... [email protected] 9 6 .#..#. .#.*.# .####. ..#... ..#... ..#... ..#... #[email protected]## .#..#. 0 0
樣例輸出
10
8
-1

之前寫了一個深搜,在做後面的題目時用深搜肯定超時超時超時,索性直接寫個廣搜,因為我感覺深搜好理解一些,一直遍歷一直遍歷找到最短的。廣搜就直接遍歷一次,使得下一次到達的點都是最小的。

這樣就很好的和佇列(先進先出)結合起來。通俗的說就是到達一個點,這個點會同時走4個方向,但是深搜的話走一個方向只有到這條路沒法走或者到終點才會返回上一個路口。從起點到終點就是建立佇列的過程

1.從起點開始,先將其加入佇列,設定步數為0

2.從佇列首端取出位置,將從這個位置能夠到達的位置加入佇列,並且讓這些位置的距離為上一個位置的距離加上1

3.迴圈2直到從佇列首端取出的是終點

最簡單的理解方法就是畫圖,結合佇列的先進先出,每到達一個點

#include<iostream>
#include<queue>
using namespace std;
typedef pair<int, int> P;
int n, m, q1, q2, z1, z2;
char a[21][21];
int pd(int i, int j){
	if (i < 0 || j < 0 || i >= n || j >= m || a[i][j] == '#')//不能出邊界
		return 0;
	return 1;
}
int main(){
	while (1){
		int map[21][21];
		cin >> n >> m;
		if (n == 0 && m == 0)
			break;
		for (int i = 0; i < n; i++){
			for (int j = 0; j < m; j++){
				cin >> a[i][j];
				map[i][j] = 1000;
				if (a[i][j] == '@'){
					q1 = i; q2 = j;
				}
				if (a[i][j] == '*'){
					z1 = i; z2 = j;
				}
			}
		}
		queue<P> que;
		map[q1][q2] = 0;
		que.push(P(q1, q2));//將起點入佇列
		while (que.size()) {
			P p = que.front(); //取得頭元素
			que.pop();
			if (p.first == z1&&p.second == z2)
				break;
			if (pd(p.first + 1, p.second) && map[p.first + 1][p.second] == 1000){//如果地圖上某一點已經走過了,那就不用走了,肯定有別的方法到達它更短
				map[p.first + 1][p.second] = map[p.first][p.second] + 1;//因為在每次處理的位置都是遞增的。走過的路不用走了,也映證了廣搜
				que.push(P(p.first + 1, p.second));
			}
			if (pd(p.first - 1, p.second) && map[p.first - 1][p.second] == 1000){
				map[p.first - 1][p.second] = map[p.first][p.second] + 1;
				que.push(P(p.first - 1, p.second));
			}
			if (pd(p.first, p.second + 1) && map[p.first][p.second + 1] == 1000){
				map[p.first][p.second + 1] = map[p.first][p.second] + 1;
				que.push(P(p.first, p.second + 1));
			}
			if (pd(p.first, p.second - 1) && map[p.first][p.second - 1] == 1000){
				map[p.first][p.second - 1] = map[p.first][p.second] + 1;
				que.push(P(p.first, p.second - 1));
			}
		}
		if (map[z1][z2] == 1000)
			printf("-1\n");
		else
			printf("%d\n", map[z1][z2]);
	}
	return 0;
}

先結合圖理解程式碼。有好的思想一起交流 實在不懂了就可以先看下:抓住那頭牛。這道題的廣搜就簡單很多 http://blog.csdn.net/qq_33193309/article/details/55260780

相關推薦

BFS迷宮尋找路徑

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

BFS (迷宮路徑)

  迷宮的最短路徑 給定一個大小為N * M 的迷宮。迷宮由通道和牆壁組成,每一步可以向鄰接的上下左右四格的通道移動。請求出從起點到終點所需的最小步數。請注意,本題假定從起點一定可以移動到終點 。 限制條件: N , M<=100 。( # . S G  分

無向圖的Dijkstra演算法任意一對頂點間的路徑迪傑斯特拉演算法

public class Main{ public static int dijkstra(int[][] w1,int start,int end) { boolean[] isLable = new boolean[w1[0].length];//是否標上所有的號 i

一個例子讓你明白一個演算法-Dijkstra源點到各頂點路徑

演算法思想 1.在一個圖中,把所有頂點分為兩個集合P,Q(P為最短路徑集合,Q為待選集合),用dis陣列儲存源點到各個頂點的最短路徑(到自身為0)。 2.初始化P集合,就是加入源點到該集合,並在ma

PAT 1111 —— Online MapDijkstra單源路徑

題目注意事項: 迪傑斯特拉兩次: 第一次求最短的路程長度【順便記錄時間用時,以判斷長度相同的時候選擇時間短的】 第二次求最短的路程時間【順便記錄到達每個點的最短路徑所需要的點數,以判斷時間相同時候選擇點數少的】【注意:第一次求得時間記錄需要重新初始化以免錯誤】

(經典的BFS和DFS運用題)

原題目來自OpenJudge 下面的都是Java實現的 先看看思路比較簡單的BFS import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import j

1(lake.pas/c/cpp)

(1)仙島求藥(lake.pas/c/cpp) 【問題描述】 少年李逍遙的嬸嬸病了,王小虎介紹他去一趟仙靈島,向仙女姐姐要仙丹救嬸嬸。叛逆但孝順的李逍遙闖進了仙靈島,克服了千險萬難來到島的中心,發現仙藥擺在了迷陣的深處。迷陣由M×N個方格組成,有的方格內有可以瞬秒李逍遙的怪物,而有的方格內則

openjudge 2727:

現在 pan blog 安全 node 大於 所在 陣列 using 2727:仙島求藥 總時間限制:1000ms內存限制:65536kB描述少年李逍遙的嬸嬸病了,王小虎介紹他去一趟仙靈島,向仙女姐姐要仙丹救嬸嬸。叛逆但孝順的李逍遙闖進了仙靈島,克服了千險萬難來到島的中

0kb step 長度 時間限制 代碼 是否 tput stream mina #include<iostream> #include<cmath> #include<cstdio> #include<algorithm>

poj 3984迷宮問題bfs路徑 類似並查集儲存上個節點 儲存路徑

迷宮問題 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16343 Accepted: 9762 Description 定義一個二維陣列: int maze[5][5] = { 0,

2727:-Openjudge

2727:仙島求藥 描述 輸入 輸出 解析 2727:仙島求藥 描述   少年李逍遙的嬸嬸病了,王小虎介紹他去一趟仙靈島,向仙女姐姐要仙丹救嬸嬸。叛逆但孝順的李逍遙闖進了仙靈島,克服了千險萬難來到島

UVa 1599 理想路徑反向BFS 路徑

ack pan clu inf struct name esp turn pop 題意: 給定一個有重邊有自環的無向圖,n個點(2 <= n <= 100000), m條邊(1 <= m <= 200000), 每條邊有一個權值, 求從第一個點到n的

HPU暑期第五次積分賽 - G-迷宮BFS+路徑

題目 程式碼 #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; int mp[110][11

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

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

資料結構::迷宮--棧的一個應用迷宮路徑

      上篇文章我們知道求解迷宮通路的方法,但是一個迷宮有時是不止一條出路,在這些出路中,我們如何找到最短的那一條,這就是我今天要說的迷宮最短路徑問題。 (此處使用的圖): 【先來分析有什麼解決方案:】 1、方法一:我們如果採用上章中遞迴的方式,將所走的路用2標記起來

用棧解決迷宮問題輸出所有路徑路徑

#include<iostream> #include<cstdio> using namespace std; #define M 4 //行數 #define N 4 //列數 #define MaxSize 100 //棧最多元素個數 int m

1003 Emergency 25 分路徑

給出N個城市,m條無向邊。每個城市中都有一定數目的救援小組,所有邊的邊權已知。現在給出起點和終點,求從起點到終點的最短路徑條數及最短經上的救緩小組數目只和。如果有多條最短路徑,則輸出數目只和最大的 Dijkstra 做法 #include<bits/stdc++.h> using nam

利用graphviz來實現無向圖視覺化路徑

1.首先下載graphviz,並安裝。 2.將輸入的邊儲存起來。 3.將最短路徑求出,並存儲每個頂點的前驅。 4.在程式中將建邊的程式碼寫入一個dot檔案中。 5.將dot檔案轉化為.png形式。 6.利用system函式開啟.png。 程式碼如下: #include &

Dijkstra--POJ 2502 Subway出所有路徑路徑

題意: 你從家往學校趕,可以用步行和乘坐地鐵這兩種方式,步行速度為10km/h,乘坐地鐵的速度為40KM/h。輸入資料的第一行資料會給你起點和終點的x和y的座標。然後會給你數目不超過200的雙向地鐵線路的站點,你可以從一個站點乘坐地鐵到下一個站點,你可以在同一線

最少步數 bfs路徑

描述 這有一個迷宮,有0~8行和0~8列:  1,1,1,1,1,1,1,1,1  1,0,0,1,0,0,1,0,1  1,0,0,1,1,0,0,0,1  1,0,1,0,1,1,0,1,1  1,0,0,0,0,1,0,0,1  1,1,0,1,0,1,0,0