华为OD机试 2024D卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试、为什么这大题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
小华按照地图去寻宝,地图上被划分成 m 行和 n 列的方格,横纵坐标范围分别是 [0, n−1]和[0, m-1]。在横坐标和纵坐标的数位之和不大于k的方格中存在黄金(每个方格中仅存在一克黄金),但横坐标和纵坐标之和大于k的方格存在危险不可进入。小华从入口(0,0)进入,任何时候只能向左,右,上,下四个方向移动一格。请问小华最多能获得多少克黄金?
二、输入描述
坐标取值范围如下:
0<=m<=50
0<=n<=50
k的取值范围如下:
0<=k<=100
输入中包含3个字数,分别是m,n,k
三、输出描述
最多能获得多少克黄金
四、测试用例
1、输入
40 40 18
2、输出
1484
3、说明
- 地图大小为 40x40。
- k 值为 18,表示坐标数位之和不大于 18 的格子中有黄金。
- 从 (0,0) 开始,通过 DFS 访问所有可以到达的格子,统计总的黄金数量。
- 最终收集到的黄金数量为 1484 克。
五、解题思路
1、深度优先搜索DFS
深度优先搜索DFS适用哪些场景?
(1)图的遍历:
DFS 是一种经典的图遍历算法,适用于需要访问图中所有节点的场景。例如,查找连通分量、路径查找等。
(2)树的遍历:
DFS 也适用于树结构的遍历,如前序遍历、中序遍历和后序遍历。用于解决树形结构的问题,如二叉树的深度、最大路径和等。
(3)连通分量:
用于查找图中的连通分量,即从一个节点出发,可以访问到的所有节点。
(4)路径和可达性问题:
用于寻找从起点到终点的路径,判断图中节点之间是否可达。例如迷宫问题、网络可达性等。
(5)拓扑排序:
在有向无环图中,DFS 可用于拓扑排序。
(6)回溯算法:
DFS 可以作为回溯算法的一部分,适用于解决组合问题、子集问题、排列问题等。例如八皇后问题、数独、解迷宫等。
(7)强连通分量:
用于求解有向图中的强连通分量,如 Tarjan 算法、Kosaraju 算法。
深度优先搜索DFS有哪些注意事项?
(1)避免重复访问:
在遍历过程中,需要标记已经访问过的节点,以避免重复访问,导致无限循环。可以使用布尔数组或集合来记录访问状态。
(2)递归深度:
在使用递归实现 DFS 时,需注意递归深度。如果图的深度过大,可能导致栈溢出。可以考虑使用显式栈来模拟递归过程。
(3)空间复杂度:
DFS 的空间复杂度主要取决于递归深度或显式栈的大小。对于非常深的图或树,需注意内存的使用。
(4)处理环:
在有向图中,需注意环的存在,避免在遍历过程中陷入无限循环。通常通过标记节点访问状态来处理。
(5)边界条件:
在递归过程中,需要处理好边界条件,确保递归能够正确结束。
(6)全局变量的使用:
在递归实现中,若使用全局变量存储结果,需要确保在每次递归调用前后维护其状态,避免影响其他递归分支。
(7)图的表示:
确保图的表示(如邻接矩阵、邻接表)能够高效地支持边的访问操作。
2、为什么采用深度优先搜索DFS?
本题的目的是在给定的二维网格地图上,从起点 (0,0) 出发,收集尽可能多的黄金。黄金分布在横坐标和纵坐标数位之和不大于 k 的格子中,移动只能在上下左右四个方向。通过深度优先搜索(DFS)来遍历所有满足条件的格子,记录并统计可以收集的黄金数量。
DFS 是一种经典的图遍历算法,适用于需要访问图中所有节点的场景。在本题中,DFS 可以用来遍历从起点 (0,0) 出发的所有满足条件的格子。
DFS 能够深入到图的每一个分支,找到所有与起始节点连通的节点。在本题中,从起点 (0,0) 开始,通过递归查找所有可以到达的格子。
对于每个格子,DFS 可以有效地访问所有满足条件的相邻格子,确保所有可能的路径都被探索。
3、具体步骤:
- 从起点 (0,0) 开始,如果当前格子的数位之和满足条件且未被访问,则收集黄金,并标记为已访问。
- 递归地访问四个相邻格子(上、下、左、右)。
- 统计并返回当前格子和所有相邻格子能收集的黄金数量。
六、Java算法源码
public class OdTest {
// 定义方向数组,表示上下左右四个方向
private static final int[] dx = {0, 0, -1, 1};
private static final int[] dy = {-1, 1, 0, 0};
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入
int m = scanner.nextInt();
int n = scanner.nextInt();
int k = scanner.nextInt();
// 记录访问状态的二维数组
boolean[][] visited = new boolean[m][n];
// 从起点(0,0)开始深度优先搜索
int goldCount = dfs(0, 0, m, n, k, visited);
// 输出结果
System.out.println(goldCount);
}
// 计算坐标数位之和的辅助函数
private static int digitSum(int x) {
int sum = 0;
while (x != 0) {
sum += x % 10;
x /= 10;
}
return sum;
}
// 深度优先搜索函数
private static int dfs(int x, int y, int m, int n, int k, boolean[][] visited) {
// 检查边界和数位之和的限制
if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y] || (digitSum(x) + digitSum(y) > k)) {
return 0;
}
// 标记当前格子为已访问
visited[x][y] = true;
// 初始化黄金数量
int goldCount = 1; // 当前格子有1克黄金
// 递归访问四个方向的相邻格子
for (int i = 0; i < 4; i++) {
goldCount += dfs(x + dx[i], y + dy[i], m, n, k, visited);
}
return goldCount;
}
}
七、效果展示
1、输入
10 10 5
2、输出
21
3、说明
地图大小为 10x10。
k 值为 5,表示坐标数位之和不大于 5 的格子中有黄金。
从 (0,0) 开始,通过 DFS 访问所有可以到达的格子,统计总的黄金数量。
最终收集到的黄金数量为 21 克。
🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 D卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试、为什么这大题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。