【LeetCode每日一题】1219. 黄金矿工

167 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

LeetCode每日一题打卡专栏正式启动!不出意外将日更LeetCode的每日一题,敬请期待。

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 个单元格中有黄金

题解(dfs+回溯)

c++定义一个默认的二维数组 static constexpr int dirs[4] [2]

c++定义一个函数 function<void(int, int, int)> dfs = [&] (int x, int y, int gold)

首先题目已经说明每次采矿需要遍历当前位置上下左右方向,说明这是一个搜索题目,再然后题目又说需要使得利益最大化,这样说明需要回溯

  • 我们需要定义一个gold去维护每次回溯所产生的收益值,并且维护一个ans求出所有路径的最大值
  • 回溯的时候当我们遍历当前点的时候定义一个变量去接收这个值,然后再让该点的值为0,最后走完的时候再把该点之前的值赋给它
  • 如果往某一个方向不会走出网格,并且走到的位置的值不为0,就可以递归搜索,在搜索完所有的方向后我们再进行回溯

c++代码

class Solution {
private: 
    static constexpr int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
public:
    int getMaximumGold(vector<vector<int>>& grid) {
         int n=grid.size(),m=grid[0].size();
         int ans=0;
         function<void(int,int,int)>dfs=[&](int x,int y,int gold){
            gold+=grid[x][y];
            ans=max(ans,gold);
​
            int idx=grid[x][y];
            grid[x][y]=0;
            for(int i=0;i<4;i++){
              int  nx=x+dir[i][0];
              int  ny=y+dir[i][1];
                if(nx>=0&&nx<n&&ny>=0&&ny<m&&grid[nx][ny]>0){
                    dfs(nx,ny,gold);
                }
            }
            grid[x][y]=idx;
         };
         for(int i=0;i<n;++i)
         for(int j=0;j<m;++j){
             if(grid[i][j]!=0)
             dfs(i,j,0);
         }
         return ans;
    }
};

Java代码

class Solution {
    int[][] g;
    int[][] 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 int[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] = 1;
                    ans = Math.max(ans, dfs(i, j));
                    vis[i][j] = 0;
                }
            }
        }
        return ans; 
    }
    int dfs(int x, int y) {
        int ans = g[x][y];
        for (int i=0;i<4;++i) {
            int nx = x + dirs[i][0];
            int ny = y + dirs[i][1];
            if(nx>=0&&nx<m&&ny>=0&&ny<n&&g[nx][ny]>0&&vis[nx][ny]==0){
            vis[nx][ny] = 1;
            ans = Math.max(ans, g[x][y] + dfs(nx, ny));
            vis[nx][ny] = 0;
            }
        }
        return ans;
    }
}