搜索—马的遍历
马的遍历
题目描述
有一个 \(n \times m\) 的棋盘,在某个点 \((x, y)\) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 \(n, m, x, y\)。
输出格式
一个 \(n \times m\) 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 \(-1\))。
样例 #1
样例输入 #1
3 3 1 1
样例输出 #1
0 3 2
3 -1 1
2 1 4
提示
数据规模与约定
对于全部的测试点,保证 \(1 \leq x \leq n \leq 400\),\(1 \leq y \leq m \leq 400\)。
分析
要求最少步数,题干是一道典型的bfs搜索题,这里要注意的是因为要输出到每个格的步数,所以需要及时记录步数,而每一格的步数是与上一个相关的,bfs,用优先队列维护找出最小。
代码实现
#include <bits/stdc++.h>
using namespace std;
int n, m;
int d[8][2] = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {2, -1}, {-2, -1}, {1, -2}, {-1, -2}};
vector<vector<int>> bfs(int x, int y) {
vector<vector<int>> ans(n + 1, vector<int>(m + 1, -1));
queue<pair<int, int>> que;
que.push({x, y});
ans[x][y] = 0;
while (!que.empty()) {
int cur_x = que.front().first;
int cur_y = que.front().second;
que.pop();
for (int i = 0; i < 8; i++) {
int xx = cur_x + d[i][0];
int yy = cur_y + d[i][1];
if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && ans[xx][yy] == -1) {
ans[xx][yy] = ans[cur_x][cur_y] + 1;
que.push({xx, yy});
}
}
}
return ans;
}
int main() {
int x, y;
cin >> n >> m >> x >> y;
vector<vector<int>> result = bfs(x, y);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << result[i][j] << " ";
}
cout << endl;
}
return 0;
}
代码解释
代码包含了必要的头文件并使用了C++标准库的命名空间。
声明了变量n和m分别表示网格的行数和列数,以及一个数组d表示八个可能的马走日移动方向。
bfs函数执行广度优先搜索。它接受起始格子坐标(x, y)作为输入,并返回一个二维向量ans,其中ans[i][j]存储了从起始格子到达格子(i, j)所需的最小移动步数。
在bfs函数内部,用起始格子初始化一个队列que。将ans向量初始化为所有值都设置为-1,除了起始格子,它被设置为0。
BFS 循环在队列不为空的情况下继续。在每次迭代中,从队列中取出前面的格子并进行检查。
对于八个可能的马走日移动方向中的每一个,通过将当前格子的坐标与相应的偏移相加,计算出新的坐标xx和yy。
如果新的坐标(xx, yy)在网格边界内,并且相应的ans值仍为-1(表示该格子尚未被访问),则将ans值更新为当前格子的ans值加1,并将新的格子坐标推入队列。
一旦 BFS 循环完成,返回包含到达每个格子所需的最小移动步数的ans向量。
在main函数中:
- 读取网格的行数、列数(
n和m)以及起始格子的坐标(x和y)。- 使用起始格子坐标调用
bfs函数,并将结果存储在result向量中。- 遍历
result向量,并打印网格中每个格子的最小移动步数。
vector<vector<int>> ans(n + 1, vector<int>(m + 1, -1));
- 初始化二维向量
ans,大小为 \((n+1) \times (m+1)\),其中 \(n\) 代表行数,\(m\) 代表列数。此二维向量用于存储每个格子到起始格子的最小移动步数。初始时,所有元素被设置为 \(-1\),表示尚未访问或未找到到达该格子的路径。
queue<pair<int, int>> que;
- 初始化队列
que,队列元素为一对整数pair<int, int>,用于表示格子的坐标 \((x, y)\)。在此算法中,队列用于实现广度优先搜索。开始时,起始格子坐标 \((x, y)\) 被添加到队列中。随后的步骤中,会不断从队列中取出格子坐标,并将其邻居的坐标加入队列,以便进一步探索这些邻居格子。

浙公网安备 33010602011771号