1. 程式人生 > 其它 >P1443 馬的遍歷(BFS廣度優先遍歷)

P1443 馬的遍歷(BFS廣度優先遍歷)

題目地址: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,太久沒敲程式碼十分生疏,想當初打前端的時候手速那個快阿。