黃金礦工

pardon110發表於2020-12-22

題面

m*n 網格 黃金礦工需要按以下規則來開採黃金,求最大

  • 每當礦工進入一個單元,就會收集該單元格中的所有黃金。
  • 礦工每次可以從當前位置向上下左右四個方向走。
  • 每個單元格只能被開採(進入)一次。
  • 不得開採(進入)黃金數目為 0 的單元格。
  • 礦工可以從網格中 任意一個 有黃金的單元格出發或者是停止
輸入: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。

思路

  • 每個網格非零值都是值得開挖的起始點
  • 每個(存在礦脈的)方格,都有四個方向可選下一步,即四叉樹
  • 顯然相同礦格挖礦之旅只能挖一次,因此需要挖時減計,挖完回填

程式碼

func getMaximumGold(grid [][]int) int {
    var ans int
    var dig func(int,int, int) int
    rows,cols := len(grid),len(grid[0])
    xy := [4]struct{x,y int}{{0,1},{0,-1},{1,0},{-1,0}} // 方向 右,左,下,上

    dig = func(x,y int, sum int) int {
        if x < 0 || y < 0 || x>=rows || y >=cols || grid[x][y] == 0 {
            return sum 
        }
        t :=grid[x][y]    // t 儲存礦脈g[x][y],便於回溯時候恢復現場
        grid[x][y] = 0
        rs := make([]int,4)
        for i,o := range xy{
            rs[i] = dig(x + o.x,y + o.y,sum + t)
        }
        grid[x][y] = t
        return max(rs...)  // 獲取從當前礦點出發能挖的最大礦量
    }

    for i:=0;i<rows;i++ {
        for j:=0;j<cols;j++ {
            if grid[i][j] != 0 {
                if cur := dig(i,j, 0); cur > ans {
                    ans = cur
                }
            }
        }
    }
    return ans
}

func max(vals...int) int {
    var max int
    for _, val := range vals {
        if val > max {
            max = val
        }
    }
    return max
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章