华为OD机试 2024C卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
宝宝和妈妈参加亲子游戏,在一个二维矩阵(N*N)的格子地图上,宝宝和妈妈抽签决定各自的位置,地图上每个格子有不同的糖果数量,部分格子有障碍物。
游戏规则是妈妈必须在最短的时间(每个单位时间只能走一步)到达宝宝的位置,路上的所有糖果都可以拿走,不能走障碍物的格子,只能上下左右走。
请问妈妈在最短到达宝宝位置的时间内最多拿到多少糖果(优先考虑最短时间到达的情况下尽可能多拿糖果)。
二、输入描述
第一行输入为 N,N 表示二维矩阵的大小。 之后 N 行,每行有 N 个值,表格矩阵每个位置的值,其中:
- -3: 妈妈
- -2: 宝宝
- -1: 障碍
- : 糖果数(0 表示没有糖果,但是可以走)
三、输出描述
输出妈妈在最短到达宝宝位置的时间内最多拿到多少糖果,行未无多余空格。
备注:地图最大 50 * 50
1、输入
4
3 2 1 -3
1 -1 1 1
1 1 -1 2
-2 1 2 3
2、输出
9
3、说明
此地图有两条最短路径可到达宝宝位置,绿色线和黄色线都是最短路径6步,但黄色拿到的糖果更多,9个。
四、解题思路
要解决这个问题,我们可以采用广度优先搜索(BFS)算法。BFS算法非常适合用于查找最短路径的问题。在这个问题中,我们需要从妈妈的位置出发,找到到达宝宝位置的最短路径,并在这条路径上尽可能多地收集糖果。
下面是解题思路:
- 初始化和输入处理:
- 读取矩阵大小 N。
- 构建二维矩阵,识别妈妈和宝宝的位置。
- 标记所有障碍物的位置。
- BFS搜索最短路径并计算最大糖果:
- 使用队列来实现BFS,从妈妈的位置开始。
- 记录每个位置的糖果数以及到达这个位置的最短时间。
- 每次从队列中取出一个位置,检查四个方向(上下左右)是否可以移动,并更新新的位置的最短时间和糖果数。
- 如果找到宝宝的位置,记录最短时间,并继续搜索其他路径,以便在最短时间内收集更多糖果。
- 输出结果:
- 输出在最短时间内能够收集到的最多糖果数。
五、Java算法源码
public class Test01 {
// Cell类,用于存储当前位置、所用时间和收集到的糖果数
static class Cell {
int x, y, time, candies;
Cell(int x, int y, int time, int candies) {
this.x = x;
this.y = y;
this.time = time;
this.candies = candies;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(); // 读取矩阵大小
int[][] grid = new int[N][N];
int momX = -1, momY = -1, babyX = -1, babyY = -1;
// 读取矩阵并定位妈妈和宝宝的位置
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
grid[i][j] = sc.nextInt();
if (grid[i][j] == -3) {
momX = i; // 记录妈妈的位置
momY = j;
} else if (grid[i][j] == -2) {
babyX = i; // 记录宝宝的位置
babyY = j;
}
}
}
// BFS初始化
int[] dx = {-1, 1, 0, 0}; // 上下左右四个方向
int[] dy = {0, 0, -1, 1};
boolean[][] visited = new boolean[N][N]; // 标记是否访问过
Queue<Cell> queue = new LinkedList<>();
queue.offer(new Cell(momX, momY, 0, 0)); // 从妈妈的位置开始
visited[momX][momY] = true;
int maxCandies = -1; // 最大糖果数
int minTime = Integer.MAX_VALUE; // 最短时间
// 开始BFS搜索
while (!queue.isEmpty()) {
Cell current = queue.poll();
// 如果到达宝宝的位置
if (current.x == babyX && current.y == babyY) {
if (current.time < minTime) {
minTime = current.time;
maxCandies = current.candies; // 更新最短时间和最大糖果数
} else if (current.time == minTime) {
maxCandies = Math.max(maxCandies, current.candies); // 在最短时间内尽量多拿糖果
}
continue;
}
// 探索四个方向的邻居节点
for (int i = 0; i < 4; i++) {
int nx = current.x + dx[i];
int ny = current.y + dy[i];
// 检查新位置是否在边界内,是否未访问过,以及是否不是障碍物
if (nx >= 0 && ny >= 0 && nx < N && ny < N && !visited[nx][ny] && grid[nx][ny] != -1) {
visited[nx][ny] = true; // 标记新位置为已访问
int newCandies = current.candies + (grid[nx][ny] > 0 ? grid[nx][ny] : 0); // 更新糖果数
queue.offer(new Cell(nx, ny, current.time + 1, newCandies)); // 将新位置加入队列
}
}
}
// 输出结果:在最短时间内能够收集到的最多糖果数
System.out.println(maxCandies);
}
}
六、效果展示
1、输入
4
3 2 1 -3
1 -1 1 1
1 1 -1 2
-2 1 2 3
2、输出
9
3、说明
此地图有两条最短路径可到达宝宝位置,绿色线和黄色线都是最短路径6步,但黄色拿到的糖果更多,9个。
🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 C卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。