路飞]_leetcode 1219. 黄金矿工

「这是我参与2022首次更文挑战的第19,活动详情查看:2022首次更文挑战

1219. 黄金矿工

你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 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 个单元格中有黄金。

分析

首先我们先根据题意了解一下如果走,也就是如果代表上下左右中四个方向。假设我们在线[2,2],我们往上走会到[2,1]、往下走会到[2,3]、往左走会到[1,2]、往左走会到[2,1]。

然后我们每走一步就会把当前位置的矿采光(当前黄金数置为0)。再根据题意中的黄金为0的矿洞我们是无法进入的,这说明俩点1正常情况下我们无法往回走、2为0的不能走,当我所在位置都不能走的情况下就结束了。

我们把所有情况都走一遍就能找出收集最多黄金的路线的。

逐步实现

定义 dirs 用于存放我们之前分析上下左右行走时计算数据。

const dirs = [[0, -1], [0, 1], [-1, 0], [1, 0]
复制代码

定义 ans 用于存放我们收集的黄金

const ans = 0
复制代码

通过俩层循环代表我们所有行走路线的起始点,当然起始点的黄金数也不能为0。

for (let i = 0; i < m; ++i) {
    for (let j = 0; j < n; ++j) {
        if (grid[i][j] !== 0) {
            dfs(i,j,0)
        }
    }
}
复制代码

每走一步都会先收集当前的黄金数并与最大数进行对比当大于最大数时,替换最大数。

const dfs = (x, y, gold) => {
    gold = gold + grid[x][y];
    ans = Math.max(ans, gold);
}
复制代码

记录当前的位置并把当前位置的黄金数设置为0。

const dfs = (x, y, gold, dirs) => {
    gold = gold + grid[x][y];
    ans = Math.max(ans, gold);
    const rec = grid[x][y];
    grid[x][y] = 0;
}

复制代码

对当前位置的上下左右四个方向进行探索,当然需要注意边界值和黄金数不能为0。这是个深度递归的过程。当我们到无路可走的地步时会回溯到当前位置方便找出所有路径并在所有路径中找到收集黄金数最大的那一条。

const dfs = (x, y, gold, dirs) => {
    gold = gold + grid[x][y];
    ans = Math.max(ans, gold);
    const rec = grid[x][y];
    grid[x][y] = 0;
    for (let d = 0; d < 4; ++d) {
        const nx = x + dirs[d][0];
        const ny = y + dirs[d][1];
       if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] > 0) {
            dfs(nx, ny, gold);
       }
    }
    grid[x][y] = rec;
}

复制代码

完整代码

/**
 * @param {number[][]} grid
 * @return {number}
 */
var getMaximumGold = function(grid) {
    const m = grid.length;
    const n = grid[0].length;
    const dirs = [[0, -1], [0, 1], [-1, 0], [1, 0]];
    let ans = 0;

    const dfs = (x, y, gold) => {
        gold = gold + grid[x][y];
        ans = Math.max(ans, gold);

        const rec = grid[x][y];
        grid[x][y] = 0;

        for (let d = 0; d < 4; ++d) {
            const nx = x + dirs[d][0];
            const ny = y + dirs[d][1];
            if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] > 0) {
                dfs(nx, ny, gold);
            }
        }

        grid[x][y] = rec;
    }
    for (let i = 0; i < m; ++i) {
        for (let j = 0; j < n; ++j) {
            if (grid[i][j] !== 0) {
                dfs(i, j, 0);
            }
        }
    }
    return ans;
};
复制代码

Guess you like

Origin juejin.im/post/7061256370229608456