搜索—马的遍历

马的遍历

题目描述

有一个 \(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++标准库的命名空间。
声明了变量 nm 分别表示网格的行数和列数,以及一个数组 d 表示八个可能的马走日移动方向。
bfs 函数执行广度优先搜索。它接受起始格子坐标 (x, y) 作为输入,并返回一个二维向量 ans,其中 ans[i][j] 存储了从起始格子到达格子 (i, j) 所需的最小移动步数。
bfs 函数内部,用起始格子初始化一个队列 que。将 ans 向量初始化为所有值都设置为 -1,除了起始格子,它被设置为 0
BFS 循环在队列不为空的情况下继续。在每次迭代中,从队列中取出前面的格子并进行检查。
对于八个可能的马走日移动方向中的每一个,通过将当前格子的坐标与相应的偏移相加,计算出新的坐标 xxyy
如果新的坐标 (xx, yy) 在网格边界内,并且相应的 ans 值仍为 -1(表示该格子尚未被访问),则将 ans 值更新为当前格子的 ans 值加 1,并将新的格子坐标推入队列。
一旦 BFS 循环完成,返回包含到达每个格子所需的最小移动步数的 ans 向量。
main 函数中:

  1. 读取网格的行数、列数(nm)以及起始格子的坐标(xy)。
  2. 使用起始格子坐标调用 bfs 函数,并将结果存储在 result 向量中。
  3. 遍历 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)\) 被添加到队列中。随后的步骤中,会不断从队列中取出格子坐标,并将其邻居的坐标加入队列,以便进一步探索这些邻居格子。
posted @ 2023-08-21 01:27  LongDz  阅读(142)  评论(0)    收藏  举报