[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

posted @ 2019-10-12 19:29  slowbird  阅读(434)  评论(0编辑  收藏  举报