[leetcode 周赛 157] 1219 黄金矿工
1219 Path with Maximum Gold 黄金矿工
问题描述
你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 m
* n
的网格 grid
进行了标注。每个单元格中的整数就表示这一单元格中的黄金数量;如果该单元格是空的,那么就是 0
。
-
为了使收益最大化,矿工需要按以下规则来开采黄金:
- 每当矿工进入一个单元,就会收集该单元格中的所有黄金。
- 矿工每次可以从当前位置向上下左右四个方向走。
- 每个单元格只能被开采(进入)一次。
- 不得开采(进入)黄金数目为
0
的单元格。 - 矿工可以从网格中 任意一个 有黄金的单元格出发或者是停止。
-
示例 1:
输入:grid = [[0,6,0],[5,8,7],[0,9,0]]
输出:24
解释:
[[0,6,0],
[5,8,7],
[0,9,0]]
一种收集最多黄金的路线是:9 -> 8 -> 7。
- 示例 2:
输入:grid = [[1,0,7],[2,0,6],[3,4,5],[0,3,0],[9,0,20]]
输出:28
解释:
[[1,0,7],
[2,0,6],
[3,4,5],
[0,3,0],
[9,0,20]]
一种收集最多黄金的路线是:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7。
- 提示:
1 <= grid.length, grid[i].length <= 15
0 <= grid[i][j] <= 100
- 最多 25 个单元格中有黄金。
思路
- 简单的DFS, 图遍历
DFS
因为数据量比较小
(只有15 * 15个可以开始遍历的位置)
暴力的以每个位置为起点, 逐个dfs遍历(四个方向, 上下左右, 遇到0或撞墙则终止), 选出所出现的最大值
代码实现
class Solution {
// 四个方向 增量 (x + dx, y + dy)
private static int[][] direct ={{0,1}, {0, -1}, {-1, 0}, {1, 0}};
// n 行数
// m 列数
// ans 最大值
private int m, n, ans = 0;
/**
* 遍历输入的(x, y), 并以其为起点进行下一次深度遍历, 遇到0或'撞墙'则终止
* @param arr 被遍历的主体
* @param x 遍历点x值
* @param y 遍历点y值
* @param cur 所进行的DFS遍历的值
*/
private void dfs(int[][] arr, int x, int y, int cur) {
// 存储当前遍历点的值
int rev = arr[x][y];
// 将其置为0 表示该位置已被遍历
arr[x][y] = 0;
// 该次DFS已遍历的值之和
cur += rev;
// 选出最大值
ans = Math.max(ans, cur);
// 向四个方向进行DFS
for (int i = 0; i < direct.length; i++) {
int nx = x + direct[i][0], ny = y + direct[i][1];
if (nx >= 0 && ny >= 0 && nx < n && ny < m && arr[nx][ny] > 0) {
//System.out.println(String.format("[%d, %d](%d)-->[%d,%d](%d) cur:%d", x, y, rev, nx, ny, arr[nx][ny], cur));
dfs(arr, nx, ny, cur);
}
}
// 遍历完成 恢复原装
arr[x][y] = rev;
}
public int getMaximumGold(int[][] grid) {
n = grid.length;
m = grid[0].length;
ans = 0;
// 暴力枚举每个位置作为DFS的起点
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] > 0) {
dfs(grid, i, j, 0);
}
}
}
return ans;
}
}
参考资源
第 157 场周赛 全球排名
【算法实况】体验使用 iPadOS 打算法竞赛 - 力扣周赛 - LeetCode Weekly 157