BFS走迷宮

題目描述

一個網格迷宮由n行m列的單元格組成,每個單元格要麼是空地(用1表示)要麼是障礙物
(用0表示)。任務是找一條從起點到終點的最短移動序列,其中UDLR代表上下左右移動到
相鄰單元格。任何時候都不能在障礙物格中,也不能走到迷宮之外。起點和終點保證是空地
n,m<=100;
在這裏插入圖片描述

思路

從迷宮的入口開始,進行層次優先遍歷(BFS,我更喜歡稱之爲層次優先遍歷,因爲這樣更形象)。BFS遍歷的關鍵就是需要用到一個隊列,在這道題中,只需要從入口點出發,依次看下它的上下左右四個結點是否可以走,如果可以走,就立即把這個結點push到隊列尾部,然後每次找的時候就是從隊頭取出一個點,依次看它的上下左右四個方向。

遍歷的路徑的時候注意是從出口往入口找,所以需要用到一個棧保存一下路徑。

其實這題難度不大,網上也有很多同志提供了代碼,代碼思路也基本和上述一樣,不過有些註釋是錯誤的!於是我分享一下我的code,如下:

#include<iostream>
#include<queue>
#include<stack>
using namespace std;
struct Node
{
	int row;
	int col;
};
#define MAXN 100
#define MAXM 100
int visit[MAXN][MAXM];
Node father[MAXN][MAXM];
queue<Node> q;
char* direction="UDLR";  // 四個方向
int dx[4] = {-1,1,0,0};	 // 四個方向對應的x方向增量
int dy[4] = {0,0,-1,1 };  // 四個方向對應的y方向增量
int maze[MAXN][MAXM];	// 迷宮各個點是否能走
int dist[MAXN][MAXM];	// 每個點到入口的最短距離
int last_dir[MAXN][MAXM];	// 每個點是從其父節點的經過何種方向走到的
int ROW,COL, xs , ys,  xt , yt; // 程序輸入的行數、列數、開始點橫縱座標、終止點橫縱座標
void bfs(int row, int col)
{
/*從第row行第col列開始進行bfs遍歷,,注意,改點爲入口點*/
	Node n;
	n.row=row;
	n.col=col;
	visit[row][col]=1;	// 設置已被訪問
	father[row][col]=n;	// 設置父親節點爲自己
	q.push(n);
	while (!q.empty())
	{
		Node front=q.front(); // 從隊列頭取出一個節點
		q.pop();
		// 依次遍歷該結點的四個方向,是否走的通
		for (int i = 0;i < 4;i++)
		{
			int x=front.row+dx[i];
			int y= front.col + dy[i];
			// 如果某個方向的一點沒出界,且沒訪問過,並且可以走
			if (x >= 0 && x<ROW && y >= 0 && y < COL && !visit[x][y] && maze[x][y])
			{
				Node node;
				node.row=x;
				node.col=y;
				visit[x][y]=1;
				father[x][y]=front;
				dist[x][y]=dist[front.row][front.col]+1;  // 到入口最短距離爲其父節點到入口最短距離+1
				last_dir[x][y]=i;	
				q.push(node); // 把改點推入隊列
			}
		}
	}

}

void print_path(int row, int col)
{
	stack<char> path;		// 用來保存輸出路徑
	/*從第row行第col列開始往前進行路徑遍歷,注意,改點爲出口點*/
	while (true)
	{
		int father_row = father[row][col].row;
		int father_col = father[row][col].col;
		// 遍歷的終止條件爲到了入口點,還記得嗎?入口點的父親節點就是自己 ==> Line 27
		if (father_row == row && father_col == col)  //到了入口點
		{
			break;
		}
		else //沒到入口點
		{
			path.push(direction[last_dir[row][col]]); // 記錄該點是怎麼從父親節點過來的
			row=father_row;
			col=father_col;
		}
	}
	while (!path.empty())  // 輸出路徑
	{
		cout<<path.top();
		path.pop();
	}
}

int main()
{
	cin >> ROW >> COL >> xs >> ys >> xt >> yt;
	for (int i = 0; i < ROW; i++) {
		for (int j = 0; j < COL ;j++) {
			cin >> maze[i][j];
		}
	}
	memset(visit, 0, sizeof(visit)); 
	bfs(xs,ys);
	cout << endl;
	print_path(xt,yt);
	cout << endl;
	return 0;
}

測試數據

樣例輸入:6行5列,入口(0,0),出口(0,4)

6 5 0 0 0 4     
1 1 0 1 1
1 0 1 1 1
1 0 1 0 0
1 0 1 1 1
1 1 1 0 1
1 1 1 1 1

輸出:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章