藍橋杯-走迷宮(BFS)

DawnTraveler發表於2024-04-12

0.題目

1.題解

1.1 BFS搜尋

思路

這裡為何使用BFS搜尋呢?由於我們求得是最短路徑,BFS廣度優先多種情況齊頭並進,必然有一種情況最先到達終止條件,這時我們直接終止搜尋即可,不像DFS深度搜尋一種情況不對還要進行回溯,造成大量重複計算.
這裡使用BFS搜尋,我們依舊要考慮終止條件,邊界條件,以及構建BFS搜尋.
1.終止條件(check函式):到達終點(x2,y2); 如果BFS搜尋結束(while迴圈結束)還沒有找到,就輸出-1
2.邊界條件(pd函式): 不可超出邊界,不可重複走,不可走有障礙的路徑
3.BFS搜尋:
3.1 初始化
3.2 外層while迴圈
3.3 內層使用簡單圖論+for訓話,表示向四周移動; 使用佇列實現BFS搜尋
3.4 使用vis陣列記錄到達當前位置步數. 1.不會重複,pd函式中有專門判斷 2.一定是最小,由於是BFS搜尋,肯定是先記錄到較小步數,之後其他較大步數不會記錄

注意:
1.這裡我使用x1,y1,x2,y2作為初始座標,發生了報錯:mathcalls.h 中已經定義了 double y1(double),後改為使用pair對直接表示
2.不要使用map關鍵字作為識別符號!!!

程式碼

#include<bits/stdc++.h>
using namespace std;
int n, m;
int Map[101][101];
int vis[101][101] = {0};
pair<int, int> Start, End;

int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};

// 路徑檢測
bool pd(int x, int y) {
	// 超出邊界
	if(x < 1 || x > n || y < 1 || y > m) {
		return false;
	}
	// 已經走過了
	if(vis[x][y] >= 1) {
		return false;
	}
	// 不是路徑不能走
	if(Map[x][y] != 1) {
		return false;
	}
	return true;
}

// 終點檢測
bool check(int x, int y) {
	if(x == End.first && y == End.second) {
		cout << vis[x][y];
		return true;
	}
	return false;
}


void BFS() {
	// 初始化
	queue<pair<int, int>> q;
	q.push(make_pair(Start.first, Start.second));
//	vis[x1][y1] = 1;

	// BFS總迴圈
	while(!q.empty()) {
		pair<int, int> tempNode = q.front();
		int x = tempNode.first;
		int y = tempNode.second;
		q.pop();
		// 進行BFS擴充套件
		for(int i = 0; i < 4; i++) {
			int newX = x + dx[i];
			int newY = y + dy[i];
			// 透過路徑檢測
			if(pd(newX, newY)) {
				// 更新vis值 
				vis[newX][newY] = vis[x][y] + 1;
				
				// 進行結果檢測
				if(check(newX, newY)) {
					exit(0);
				}
				
				// 不是最終點,更新佇列
				q.push(make_pair(newX, newY)); 
			}
		}
	}
	cout << -1;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> Map[i][j];
		}
	}
	cin >> Start.first >> Start.second >> End.first >> End.second;
	BFS();
}