网络异常,图片无法展示
|
题目描述
这是 LeetCode 上的 1219. 黄金矿工 ,难度为 中等。
Tag : 「图论搜索」、「DFS」、「回溯算法」
你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 m * n
的网格 gridgrid 进行了标注。每个单元格中的整数就表示这一单元格中的黄金数量;如果该单元格是空的,那么就是 00。
为了使收益最大化,矿工需要按以下规则来开采黄金:
- 每当矿工进入一个单元,就会收集该单元格中的所有黄金。
- 矿工每次可以从当前位置向上下左右四个方向走。
- 每个单元格只能被开采(进入)一次。
- 不得开采(进入)黄金数目为 00 的单元格。
- 矿工可以从网格中 任意一个 有黄金的单元格出发或者是停止。
示例 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 <= 151<=grid.length,grid[i].length<=15
- 0 <= grid[i][j] <= 1000<=grid[i][j]<=100
- 最多 $254 个单元格中有黄金。
回溯算法
根据题意,我们可以枚举每个黄金点作为起点,然后使用 DFS
回溯搜索以该点作为起点所能得到的最大收益。
代码:
class Solution { int[][] g; boolean[][] vis; int m, n; int[][] dirs = new int[][]{{1,0},{-1,0},{0,1},{0,-1}}; public int getMaximumGold(int[][] grid) { g = grid; m = g.length; n = g[0].length; vis = new boolean[m][n]; int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (g[i][j] != 0) { vis[i][j] = true; ans = Math.max(ans, dfs(i, j)); vis[i][j] = false; } } } return ans; } int dfs(int x, int y) { int ans = g[x][y]; for (int[] d : dirs) { int nx = x + d[0], ny = y + d[1]; if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue; if (g[nx][ny] == 0) continue; if (vis[nx][ny]) continue; vis[nx][ny] = true; ans = Math.max(ans, g[x][y] + dfs(nx, ny)); vis[nx][ny] = false; } return ans; } } 复制代码
- 时间复杂度:爆搜复杂度为指数级别,分析时空复杂度意义不大
- 空间复杂度:爆搜复杂度为指数级别,分析时空复杂度意义不大
最后
这是我们「刷穿 LeetCode」系列文章的第 No.1219
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour… 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。