目录
- 专栏导读
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 四、解题思路
- 五、Java算法源码
- 六、效果展示
- 1、输入
- 2、输出
- 3、说明
华为OD机试 2023B卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
有M*N的节点矩阵,每个节点可以向8个方向(上下左右及四个斜线防线)转发数据包,每个节点转发时会消耗固定时延,连续两个相同时延可以减少一个时延值(即当有K个相同时延的节点连续转发时可以减少K-1个时延值),求左上角(0,0)开始转发数据包到右下角(M-1,N-1)并转发出的最短时延。
二、输入描述
第一行两个数字,M,N,接下来有M行,每行有N个数据,表示M*N的矩阵。
三、输出描述
最短时延值。
四、解题思路
- 第一行输入矩阵的行数M和矩阵的列数N;
- 接下来有M行,每行有N个数据,表示M*N的矩阵;
- 定义矩阵的二维数组,并将输入值加入到二维数组;
- 定义集合delayList,存储所有到达终点的路径的延迟时间;
- 定义集合pathSet,存储当前路径中已经访问过的位置;
- 将起点加入路径中;
- 从起点开始遍历矩阵;
- 判断是否到达终点;
- 更新延迟时间;
- 将当前的延迟时间加入结果列表;
- 遍历八个方向;
- 判断新的位置是否越界且是否已经访问过;
- 将新的位置加入路径中;
- 递归遍历新的位置;
- 将新的位置从路径中删除,回溯到上一步;
- 输出所有到达终点的路径中的最小延迟时间。
五、Java算法源码
package com.guor.od;
import java.util.*;
import java.util.regex.Pattern;
public class OdTest {
// 矩阵的行数
static int M;
// 矩阵的列数
static int N;
// 存储矩阵的二维数组
static int[][] matrix;
static int[][] offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; // 存储八个方向的偏移量
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 输入矩阵的行数
M = scanner.nextInt();
// 输入矩阵的列数
N = scanner.nextInt();
// 初始化矩阵的二维数组
matrix = new int[M][N];
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
// 输入矩阵的每个元素
matrix[i][j] = scanner.nextInt();
}
}
// 存储所有到达终点的路径的延迟时间
List<Integer> delayList = new ArrayList<>();
// 存储当前路径中已经访问过的位置
Set<Integer> pathSet = new HashSet<>();
// 将起点加入路径中
pathSet.add(0);
// 从起点开始遍历矩阵
dfs(0, 0, 0, Integer.MAX_VALUE, pathSet, delayList);
// 输出所有到达终点的路径中的最小延迟时间
System.out.println(Collections.min(delayList));
}
private static void dfs(int i, int j, int delay, int last, Set<Integer> pathSet, List<Integer> delayList) {
// 当前位置的值
int cur = matrix[i][j];
// 判断是否需要等待一秒
boolean flag = cur == last;
// 到达终点
if (i == M - 1 && j == N - 1) {
// 更新延迟时间
delay += cur - (flag ? 1 : 0);
// 将当前的延迟时间加入结果列表
delayList.add(delay);
return;
}
// 遍历八个方向
for (int[] offset : offsets) {
// 新的行坐标
int new_i = i + offset[0];
// 新的列坐标
int new_j = j + offset[1];
// 将二维坐标转换为一维坐标
int pos = new_i * N + new_j;
// 判断新的位置是否越界且是否已经访问过
if (new_i >= 0 && new_i < M && new_j >= 0 && new_j < N && !pathSet.contains(pos)) {
// 将新的位置加入路径中
pathSet.add(pos);
// 递归遍历新的位置
dfs(new_i, new_j, delay + cur - (flag ? 1 : 0), cur, pathSet, delayList);
// 将新的位置从路径中删除,回溯到上一步
pathSet.remove(pos);
}
}
}
}
六、效果展示
1、输入
3 3
2 2 2
2 2 2
2 2 2
2、输出
4
3、说明
(2+2+2-(3-1))
🏆下一篇:华为OD机试真题 Java 实现【路灯照明问题】【2022Q4 100分】,感谢fly晨发现这个问题,并提供更优质的算法
🏆本文收录于,华为OD机试(JAVA)真题(A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。