題目描述
一個網格迷宮由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
輸出: