leetcode:禮物的最大價值

題目來源:力扣

題目描述:

在一個 m*n 的棋盤的每一格都放有一個禮物,每個禮物都有一定的價值(價值大於 0)。你可以從棋盤的左上角開始拿格子裏的禮物,並每次向右或者向下移動一格、直到到達棋盤的右下角。給定一個棋盤及其上面的禮物的價值,請計算你最多能拿到多少價值的禮物?
=============================================
示例 1:
輸入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
輸出: 12
解釋: 路徑 1→3→5→2→1 可以拿到最多價值的禮物
===========================================

審題:

本題屬於一道較簡單的動態規劃類題目.還是按照步驟一步步來分析.剛開始學習動態規劃時,就像小時候解題一樣,一步步理清自己的思路是非常重要的.按步驟慢慢來.

  • 分析最優子結構
    假設我們當前位於位置(i, j),我們想計算從該位置出發所能拿到的最多價值禮物, 由於我們每一步可以向右移動或向下移動,因此假設我們知道位置(i+1, j)以及位置(i, j+1)處我們所能拿到的最多價值禮物,我們便可以作出判斷,在位置(i, j)處,我們應該向右還是向下移動. 基於該最優子結構,我們進一步分析子問題是否存在重疊. 分析不難發現, 爲了計算(i, j)處最優方案,我們需要計算(i, j+1)處最優方案.而爲了計算(i-1, j+1), 我們同樣需要計算(i, j+1)處最優方案, 因此子問題存在重疊

  • 分析狀態變量
    該問題狀態變量較爲簡單, 即爲當前所處位置. 由於是二維座標, 因此我們可以使用二維數組存儲每一狀態處的最優方案. S[i][j]表示從位置(i, j)出發, 所能拿到的價值.

  • 確定狀態轉移方程
    S[i][j]=grid[i][j]+max(S[i+1][j],S[i][j+1])S[i][j] = grid[i][j] + max(S[i+1][j], S[i][j+1])
    其中基礎情形爲S[grid.length1][grid[0].length1]=grid[grid.length1][grid[0].length1]S[grid.length-1][grid[0].length-1] = grid[grid.length-1][grid[0].length-1]
    因此, 從左上角出發, 所能獲取的最多價值禮物爲S[0][0];

java算法:

class Solution {
    public int maxValue(int[][] grid) {
        //狀態變量爲當前位置
        int S[][] = new int[grid.length][grid[0].length];
        int row = grid.length;
        int col = grid[0].length;
        //基礎情形
        S[row-1][col-1] = grid[row-1][col-1];
        
        for(int i = row-1; i >= 0; i--){
            for(int j = col-1; j >= 0; j--){
                if(i + 1 < row){
                    S[i][j] = Math.max(S[i][j], grid[i][j] + S[i+1][j]);
                }
                if(j+1 < col){
                    S[i][j] = Math.max(S[i][j], grid[i][j] + S[i][j+1]);
                }
            }
        }
        return S[0][0];
    }
}

降低空間複雜度值O(1)

在初始版本中,由於我們使用額外的數組S保存各狀態時的最優方案, 因此空間複雜度爲O(MN). 通過分析, 我們發現我們可以直接更改grid[i][j]上的元素, 在計算完(i, j)處最優方案後,使用grid[i][j]儲存位置(i, j)處最優方案.

class Solution {
    public int maxValue(int[][] grid) {
        //狀態變量爲當前位置
        //int S[][] = new int[grid.length][grid[0].length];
        int row = grid.length;
        int col = grid[0].length;
        for(int i = row-1; i >= 0; i--){
            for(int j = col-1; j >= 0; j--){
                int sum = 0;
                if(i + 1 < row){
                    sum = Math.max(sum, grid[i+1][j]);
                }
                if(j+1 < col){
                    sum = Math.max(sum,grid[i][j+1]);
                }
                grid[i][j] += sum;
            }
        }
        return grid[0][0];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章