题解 | 量子网络穿梭(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; }#华为机考#