1. 题目
读题
游戏中心的运营小伙伴最近接到一款新游戏的上架申请,为了保障用户体验,运营同学将按运营流程和规范对其做出分析评估。经过初步了解后分析得知,该游戏的地图可以用一个大小为 n*n 的矩阵表示,每个元素可以视为一个格子,根据游戏剧情设定其中某些格子是不可达的(比如建筑、高山、河流或者其它障碍物等),现在请你设计一种算法寻找从起点出发到达终点的最优抵达路径,以协助运营小伙伴评估该游戏的可玩性和上手难度。
输入描述:
第一行表示矩阵大小 n,5 <n < 10000
第二行表示起点和终点的坐标
第三行起是一个用矩阵表示的游戏地图,其中#或者@表示障碍物,其他字母、非0数字、以及符号+、-、* 等等均表示普通可达格子,共有 n 行 n 列
输出描述:
输出最优路径的长度;若无法到达,则输出-1
考查点
游戏地图路径的编程题涉及到以下几个方面的知识:
- 矩阵的表示和操作:如何用二维数组或其他数据结构来存储和访问游戏地图中的每个格子,以及如何判断格子的属性(如是否可通行,是否有障碍物等)。
- 搜索算法的原理和实现:如何用深度优先搜索(DFS)或广度优先搜索(BFS)等算法来遍历游戏地图中的所有可能的路径,以及如何记录和更新路径的长度和方向。
- 优化策略的应用和分析:如何用启发式函数(如曼哈顿距离,欧几里得距离等)来估计当前位置到目标位置的距离,以及如何用优先队列(如堆,二叉树等)来存储和排序待扩展的节点,从而提高搜索效率和准确性。
2. 解法
思路
参照 :https://blog.csdn.net/qq_43637079/article/details/111192994
BFS介绍
BFS:宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
BFS 的核心思想就是把一些问题抽象成图,从一个点开始,向四周开始扩散。一般来说,我们写 BFS 算法都是用「队列」这种数据结构,每次将一个节点周围的所有节点加入队列。
BFS 出现的常见场景,问题的本质就是让你在一幅「图」中找到从起点start到终点target的最近距离。
嘛意思呢,假设你进入一个迷宫,里面有各个分叉口,你刚开始从入口进入,当走到分叉口的时候,在求生技能的加持下,你学会了分身术。每当你走到分叉口,你都分身成好几个你分别进入还没走过的通道。各自探寻下一个分叉口。只要其中一个找到了出口,求生技能就会发挥作用,将你的所有元神召集在出口处合并,然后成功走出迷宫。走出迷宫的路径(步数)就是找到出口的这个分身所走的路径,也就是最短路径
代码逻辑
具体实现
// 定义四个方向
int[] dx = {0, 0, -1, 1};
int[] dy = {-1, 1, 0, 0};
// 定义BFS函数
public int bfs(char[][] grid, int start_x, int start_y, int end_x, int end_y) {
// 获取矩阵大小
int n = grid.length;
// 初始化状态数组
int[][] state = new int[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(state[i], Integer.MAX_VALUE); // 将所有格子标记为无穷大
}
state[start_x][start_y] = 99; // 起点标记为99
state[end_x][end_y] = 99; // 终点标记为99
// 初始化队列
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{start_x, start_y}); // 将起点加入队列
// 初始化距离
int dist = 0;
// 循环直到队列为空或找到终点
while (!queue.isEmpty()) {
// 获取当前层的大小
int size = queue.size();
// 遍历当前层的每个格子
for (int i = 0; i < size; i++) {
// 取出队首元素
int[] cur = queue.poll();
int x = cur[0];
int y = cur[1];
// 检查是否到达终点
if (x == end_x && y == end_y) {
return dist;
}
// 遍历四个方向
for (int j = 0; j < 4; j++) {
// 计算邻居坐标
int nx = x + dx[j];
int ny = y + dy[j];
// 判断邻居是否有效并且可达
if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] != '#' && grid[nx][ny] != '@' && state[nx][ny] == Integer.MAX_VALUE) {
// 将邻居入队并更新状态
queue.offer(new int[]{nx, ny});
state[nx][ny] = dist + 1;
}
}
}
// 增加距离
dist++;
}
// 如果没有找到路径,返回-1
return -1;
}