当前位置: 首页> 游戏> 游戏 > 华为OD机试 - 跳马 - 广度优先搜索BFS(Java 2024 D卷 200分)

华为OD机试 - 跳马 - 广度优先搜索BFS(Java 2024 D卷 200分)

时间:2025/7/13 5:39:27来源:https://blog.csdn.net/guorui_java/article/details/139700701 浏览次数:0次

在这里插入图片描述

华为OD机试 2024D卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)》。

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

马是象棋(包括中国象棋只和国际象棋)中的棋子,走法是每步直一格再斜一格,即先横着或直着走一格,然后再斜着走一个对角线,可进可退,可越过河界,俗称马走 “日“ 字。

给项m行n列的棋盘(网格图),棋盘上只有象棋中的棋子“马”,并目每个棋子有等级之分,等级为K的马可以跳1~k步(走的方式与象棋中“马”的规则一样,不可以超出棋盘位置),问是否能将所有马跳到同一位置,如果存在,输出最少需要的总步数(每匹马的步数相加) ,不存在则输出-1。

注意:

允许不同的马在跳的过程中跳到同一位置,坐标为(x,y)的马跳一次可以跳到到坐标为(x+1,y+2),(x+1,y-2),(x+2,y+1),(x+2,y-1). (x-1,y+2),(x-1,y-2),(x-2,y+1),(x-2,y-1),的格点上,但是不可以超出棋盘范围。

二、输入描述

第一行输入m,n代表m行n列的网格图棋盘(1 <= m,n <= 25);

接下来输入m行n列的网格图棋盘,如果第i行,第j列的元素为 “.” 代表此格点没有棋子,如果为数字k (1<= k <=9),代表此格点存在等级为的“马”。

三、输出描述

输出最少需要的总步数 (每匹马的步数相加),不存在则输出-1。

1、输入

3 2

2.

2、输出

0

3、说明

四、解题思路

  1. 棋盘的遍历和马的跳跃规则:
    • 我们需要模拟马在棋盘上的跳跃,确定所有马是否能到达同一个位置。
    • 每个等级为 k 的马可以跳 1 到 k 步,但依然遵循“日”字跳跃规则。
  2. 广度优先搜索(BFS):
    • 对于每个马的位置,使用广度优先搜索计算从该位置到所有其他位置的最小步数。
    • 记录每个马从其起点位置到达所有其他位置的步数。
  3. 最小步数计算:
    • 对于每个可能的目标位置,计算所有马到达该位置的总步数。
    • 找到最小的总步数,如果存在这样的总步数,则输出;否则输出 -1。

五、Java算法源码

public class Test01 {private static final int[][] DIRECTIONS = {{1, 2}, {1, -2}, {2, 1}, {2, -1},{-1, 2}, {-1, -2}, {-2, 1}, {-2, -1}};public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 读取棋盘的行数和列数int m = scanner.nextInt();int n = scanner.nextInt();scanner.nextLine(); // 读取换行符char[][] board = new char[m][n];List<int[]> horses = new ArrayList<>();// 读取棋盘数据for (int i = 0; i < m; i++) {String line = scanner.nextLine();for (int j = 0; j < n; j++) {board[i][j] = line.charAt(j);if (board[i][j] != '.') {horses.add(new int[]{i, j, board[i][j] - '0'}); // 记录马的位置和等级}}}// 关闭Scannerscanner.close();// 计算最小总步数int result = findMinimumTotalSteps(board, horses, m, n);System.out.println(result);}// 计算最小总步数private static int findMinimumTotalSteps(char[][] board, List<int[]> horses, int m, int n) {int minSteps = Integer.MAX_VALUE;boolean isReachable = false;// 遍历每个格点作为目标位置for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {int totalSteps = 0;boolean allReachable = true;for (int[] horse : horses) {int steps = bfs(board, horse, i, j, m, n);if (steps == -1) {allReachable = false;break;}totalSteps += steps;}if (allReachable) {isReachable = true;minSteps = Math.min(minSteps, totalSteps);}}}return isReachable ? minSteps : -1;}// 广度优先搜索计算从起点到目标位置的最小步数private static int bfs(char[][] board, int[] horse, int targetX, int targetY, int m, int n) {int startX = horse[0];int startY = horse[1];int level = horse[2];if (startX == targetX && startY == targetY) {return 0;}boolean[][] visited = new boolean[m][n];Queue<int[]> queue = new LinkedList<>();queue.add(new int[]{startX, startY, 0}); // (x, y, steps)visited[startX][startY] = true;while (!queue.isEmpty()) {int[] current = queue.poll();int x = current[0];int y = current[1];int steps = current[2];for (int k = 1; k <= level; k++) {for (int[] direction : DIRECTIONS) {int newX = x + k * direction[0];int newY = y + k * direction[1];if (newX == targetX && newY == targetY) {return steps + 1;}if (isValid(newX, newY, m, n) && !visited[newX][newY]) {visited[newX][newY] = true;queue.add(new int[]{newX, newY, steps + 1});}}}}return -1;}// 检查坐标是否在棋盘范围内private static boolean isValid(int x, int y, int m, int n) {return x >= 0 && x < m && y >= 0 && y < n;}
}

六、效果展示

1、输入

3 5
47.48
4744.
7…

2、输出

16

3、说明

在这里插入图片描述


🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 C卷 200分)

🏆本文收录于,华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

关键字:华为OD机试 - 跳马 - 广度优先搜索BFS(Java 2024 D卷 200分)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: