Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

黄金矿工-1219 #105

Open
sl1673495 opened this issue Jun 27, 2020 · 1 comment
Open

黄金矿工-1219 #105

sl1673495 opened this issue Jun 27, 2020 · 1 comment

Comments

@sl1673495
Copy link
Owner

sl1673495 commented Jun 27, 2020

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-with-maximum-gold
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

题目很好玩,看起来像游戏一样,但是本质上还是在一个「二维矩阵」中做递归回溯的求解。

分别尝试以任意一个不为 0的格子作为起点,不断的向「上、下、左、右」四个方向继续的递归求解,一旦遇到边界了(比如超出边界,或者当前格子为 0 了)就把目前得到的值和全局的最大值 maxGold 比较,更新最大值

考虑清楚每次遍历四周的格子前的判断条件:

  1. 范围不能越界
  2. 本轮递归中未访问过
  3. 下一个格子的值不能为 0
/**
 * @param {number[][]} grid
 * @return {number}
 */
let getMaximumGold = function (grid) {
  let maxY = grid.length
  if (maxY === 0) {
    return 0
  }
  let maxX = grid[0].length

  let visited = []
  for (let y = 0; y < maxY; y++) {
    visited[y] = []
  }

  let dirs = [[1, 0],[-1, 0],[0, -1],[0, 1]]

  // 验证是否能走入这个格子
  // 1. 范围不能越界
  // 2. 本轮递归中未访问过
  // 3. 格子的值不能为 0
  let isValid = (y, x) => {
    return (y >= 0 && y < maxY) && 
    (x >= 0 && x < maxX) && 
    grid[y][x] !== 0 && 
    !visited[y][x]
  }

  let maxGold = 0
  let helper = (y, x, prevGold) => {
    let val = grid[y][x]
    let curGold = prevGold + val
    if (curGold === 0) {
      return
    }

    for (let dir of dirs) {
      let [diffY, diffX] = dir
      let nextY = y + diffY
      let nextX = x + diffX
      if (isValid(nextY, nextX)) {
        visited[y][x] = true
        helper(nextY, nextX, curGold)
        visited[y][x] = false
      } else {
        // 走到尽头或者不符合条件的了
        maxGold = Math.max(maxGold, curGold)
      }
    }
  }

  for (let y = 0; y < maxY; y++) {
    for (let x = 0; x < maxX; x++) {
      helper(y, x, 0)
    }
  }

  return maxGold
}
@daomingQian
Copy link

双百解答

var getMaximumGold = function (grid) {
        let max = 0
        const leni = grid.length
        const lenj = grid[0].length
        function dfs(i, j) {
          const cur = grid[i][j]
          let t1 = 0,
            t2 = 0,
            t3 = 0,
            t4 = 0
          grid[i][j] = 0
          if (i + 1 < leni && grid[i + 1][j] !== 0) {
            t1 = dfs(i + 1, j)
          }
          if (i - 1 >= 0 && grid[i - 1][j] !== 0) {
            t2 = dfs(i - 1, j)
          }
          if (j + 1 < lenj && grid[i][j + 1] !== 0) {
            t3 = dfs(i, j + 1)
          }
          if (j - 1 >= 0 && grid[i][j - 1] !== 0) {
            t4 = dfs(i, j - 1)
          }
          grid[i][j] = cur

          return grid[i][j] + Math.max(t1, t2, t3, t4)
        }

        for (let i = 0; i < leni; i++) {
          for (let j = 0; j < lenj; j++) {
            if (grid[i][j]) {
              max = Math.max(max, dfs(i, j))
            }
          }
        }

        return max;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants