题解 | 量子网络穿梭(BFS)

量子网络穿梭

https://www.nowcoder.com/practice/1352032ab7744c148577c0d05eff841b

C++版本

// C++版本
#include <iostream>
#include <queue>
#include <vector>

// 路的类型
enum class Road : char {
    START = 'S',
    END = 'E',
    WALL = '1',
    GATE = '2',
};

// 坐标类型
struct Point {
    int x, y;

    Point() = delete;
    Point(const int _x, const int _y) : x(_x), y(_y) {}
    Point operator+(const Point& _p) const { return {x + _p.x, y + _p.y}; }
    bool operator==(const Point& _p) const { return x == _p.x && y == _p.y; }
    bool operator!=(const Point& _p) const { return !operator==(_p); }
    ~Point() = default;
};

// 二维矩阵类型
template<typename T>
using grid_t = std::vector<std::vector<T>>;

// 能否可走判断
inline bool cango(const grid_t<char>& g, const Point& p, const grid_t<int>& d) {
    const int m = static_cast<int>(g.size());
    const int n = static_cast<int>(g[0].size());
    return p.x >= 0 && p.x < m && p.y >= 0 && p.y < n && g[p.x][p.y] != static_cast<char>(Road::WALL) && d[p.x][p.y] == -1;
}

// 广度优先遍历
int bfs(const grid_t<char>& grid, const Point& start, const Point& end, const std::vector<Point>& gates) {
    const int m = static_cast<int>(grid.size());
    const int n = static_cast<int>(grid[0].size());
    std::queue<Point> queue;  // BFS 辅助队列
    grid_t<int> distance(m, std::vector<int>(n, -1));  // 记录到达每个位置的最短时间
    const std::vector<Point> directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};  // 方向

    // 广度优先遍历
    queue.push(start);
    distance[start.x][start.y] = 0;
    while (!queue.empty()) {
        Point current = queue.front();
        queue.pop();

        if (current == end) break;  // 到达终点

        // 试探四个方向
        for (const Point& direction : directions) {
            Point next = current + direction;  // 尝试移动
            if (!cango(grid, next, distance)) continue;

            // 1. 尝试传送门:所有传送门走一遍(没访问过的才能走)
            if (grid[next.x][next.y] == static_cast<char>(Road::GATE)) {
                for (const Point& gate : gates) {
                    distance[gate.x][gate.y] = distance[current.x][current.y] + 1;
                    queue.push(gate);
                }
            } else {  // 2. 尝试普通的路:没走过的相邻的路走一遍
                distance[next.x][next.y] = distance[current.x][current.y] + 1;
                queue.push(next);
            }
        }
    }
    return distance[end.x][end.y];
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int m, n;  // 地图尺寸
    std::cin >> m >> n;

    grid_t<char> grid(m, std::vector<char>(n));  // 地图信息
    Point start(0, 0), end(0, 0);  // 起点和终点坐标
    std::vector<Point> gates;  // 传送门坐标

    // 记录特殊位置
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            std::cin >> grid[i][j];
            if (grid[i][j] == static_cast<char>(Road::WALL) || grid[i][j] == '\n') continue;
            if (grid[i][j] == static_cast<char>(Road::START)) {
                start = {i, j};
            } else if (grid[i][j] == static_cast<char>(Road::END)) {
                end = {i, j};
            } else if (grid[i][j] == static_cast<char>(Road::GATE)) {
                gates.emplace_back(i, j);
            }
        }
    }

    std::cout << bfs(grid, start, end, gates) << std::endl;

    return 0;
}

C语言版本

// C语言版本
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

// 地图尺寸
#define GRID_MAX_SIZE 50
// 传送门最大数量
#define GATE_MAX_COUNT 4

typedef struct Point Point;
typedef struct Queue Queue;

// 路的类型
enum Road {
    START = 'S',
    END = 'E',
    WALL = '1',
    GATE = '2',
};

// 坐标类型
struct Point {
    int x, y;
};

// 数组队列结构
struct Queue {
    Point data[(GRID_MAX_SIZE * GRID_MAX_SIZE) / 2];
    unsigned int front;
    unsigned int back;
    unsigned int size;
};

// 队列初始化
void queue_init(Queue *queue) {
    queue->front = 0;
    queue->back = 0;
    queue->size = 0;
}

// 入队
void queue_push(Queue *queue, Point *point) {
    if (queue->size < GRID_MAX_SIZE * GRID_MAX_SIZE) {
        queue->data[queue->back++] = *point;
        queue->size++;
        if (queue->back == GRID_MAX_SIZE * GRID_MAX_SIZE) queue->back = 0;
    }
}

// 出队
void queue_pop(Queue *queue, Point *point) {
    if (queue->size > 0) {
        *point = queue->data[queue->front++];
        queue->size--;
        if (queue->front == GRID_MAX_SIZE * GRID_MAX_SIZE) queue->front = 0;
    }
}

// 是否可走
bool cango(int m, int n, char (*grid)[GRID_MAX_SIZE], int (*d)[GRID_MAX_SIZE], Point *p) {
    return p->x >= 0 && p->x < m && p->y >= 0 && p->y < n && grid[p->x][p->y] != WALL && d[p->x][p->y] == -1;
}

// 广度优先遍历
int bfs(int m, int n, char (*grid)[GRID_MAX_SIZE], Point *start, Point *end, int gate_count, Point *gates) {
    Queue queue;
    queue_init(&queue);
    int distance[GRID_MAX_SIZE][GRID_MAX_SIZE];
    Point directions[4] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};

    // 初始化 distance
    memset(distance, -1, sizeof(distance));

    distance[start->x][start->y] = 0;
    queue_push(&queue, start);
    while (queue.size) {
        Point current;
        queue_pop(&queue, ¤t);

        if (current.x == end->x && current.y == end->y) break;  // 到达终点

        // 试探四个方向
        for (unsigned int i = 0; i < 4; ++i) {
            Point next = {current.x + directions[i].x, current.y + directions[i].y};
            if (!cango(m, n, grid, distance, &next)) continue;

            // 1. 尝试所有传送门(未走过的)
            if (grid[next.x][next.y] == GATE) {
                for (unsigned int j = 0; j < gate_count; ++j) {
                    if (distance[gates[j].x][gates[j].y] == -1) {
                        distance[gates[j].x][gates[j].y] = distance[current.x][current.y] + 1;
                        queue_push(&queue, &gates[j]);
                    }
                }
            } else {  // 2. 尝试相邻的所有普通路(未走过的)
                distance[next.x][next.y] = distance[current.x][current.y] + 1;
                queue_push(&queue, &next);
            }
        }
    }

    return distance[end->x][end->y];
}

int main() {
    int m, n;
    scanf("%d %d", &m, &n);
    getchar();  // 清除换行符

    char grid[GRID_MAX_SIZE][GRID_MAX_SIZE];  // 地图信息
    Point start, end;  // 起点和终点
    Point gates[GATE_MAX_COUNT];  // 传送门位置信息
    unsigned int gate_count = 0;  // 传送门数量

    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            grid[i][j] = getchar();
            if (grid[i][j] == WALL) continue;
            if (grid[i][j] == START) {
                start = (Point){i, j};
            } else if (grid[i][j] == END) {
                end = (Point){i, j};
            } else if (grid[i][j] == GATE) {
                gates[gate_count++] = (Point){i, j};
            }
        }
        getchar();  // 清除换行符
    }

    printf("%d\n", bfs(m, n, grid, &start, &end, gate_count, gates));

    return 0;
}

#华为机考#
全部评论

相关推荐

评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务