P1443 馬的遍歷(BFS廣度優先遍歷)
阿新 • • 發佈:2022-01-12
題目地址:P1443 馬的遍歷 - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)
思路:
復讀廣度優先遍歷的思路:
廣度優先搜尋演算法的基本思想: 1、對於初始狀態入隊,設定初始狀態為已訪問。 2、如果佇列不為空時,出隊隊頭元素,否則跳到第五步。 3、檢查出隊的元素,檢查所有相鄰狀態,如果有效且未訪問,則將所有有效的相鄰狀態進行入隊,並且設定這些狀態為已訪問,然後跳到第二部重複執行。 4、對於所有出隊的元素,檢查所有相鄰狀態,如果有效且未訪問,則所有有效的相鄰元素進行入隊,並且設定這些狀態為已訪問,然後跳到第二步重複執行。 5、檢查最後出隊的元素是否為最終解,如果是輸出結果,否則說明無解。
這裡的馬用的是中國象棋的馬,可以走一個“日”字形的格子,即x增或減1,y增或減2或者x增或減2,y增或減1。假設馬在一個無限大的格子的某一個位置上,此時馬可以有八種走法:
此時只需把馬可以走的位置依次入隊計算即可。
樣例解析:
初始狀態,馬能去這倆地方
這兩匹馬能去的有
以此類推即可。如果還不會可以自己畫圖。(懶得畫了)
AC程式碼
#include <iostream> #include <queue> using namespace std; int n, m, x, y; int visited[405][405];//這裡visited不僅拿來記錄有無使用過,同時拿來記錄幾步可以到這裡 int work[][3] = {{1,2},{2,1},{-1,2},{-2,1},{-1,-2},{1,-2},{2,-1},{-2,-1}}; //將八種的移動情況的座標全部列舉為陣列方便使用 struct node { int x, y; int step; //x,y是當前位置,step是當前步數 node(int x_,int y_,int step_) { x = x_; y = y_; step = step_; } node() { step = -1; } }; queue<node>q; int main(int argc, char* argv[]) { cin >> n >> m >> x >> y; node a = node(x, y, 0);//從初始點開始入隊遍歷 q.push(a); visited[x][y] = -2;//為了避免誤判,隨便把初始點設一個數字表示這個點用過了 while (!q.empty()) { node t = q.front(); q.pop(); for(int i=0;i<8;i++) { if((t.x+work[i][0]>=1&& t.y + work[i][1]>=1&& t.x + work[i][0] <= n&& t.y + work[i][1]<=m)&&!visited[t.x+work[i][0]][t.y+work[i][1]]) {//判斷八種情況能不能走,能則入隊 node temp = node(t.x + work[i][0], t.y + work[i][1], t.step + 1); q.push(temp); visited[t.x + work[i][0]][t.y + work[i][1]] = temp.step; } } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if (i == x && j == y) {//初始點是第零步就可以到達,所以直接輸出0 printf("%-5d", 0); continue; } if (!visited[i][j]) {//到不了的是0,這裡改成-1輸出 printf("%-5d", -1); } else printf("%-5d", visited[i][j]); } cout << endl; } return 0; }
心得:
完全自己寫了一次BFS,太久沒敲程式碼十分生疏,想當初打前端的時候手速那個快阿。