動態規劃之最短路徑和

給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和爲最小。java

**說明:**每次只能向下或者向右移動一步。算法

示例:數組

輸入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
輸出: 7
解釋: 由於路徑 1→3→1→1→1 的總和最小。
複製代碼

昨天作了道算法題,感受畫圖頗有助於本身理解算法的過程,此次再挑一個算法加深印象。碰到這種類型的題目,和遞歸很像,可是使用遞歸,若是數據範圍比較大,就會花費很長時間。bash

動態規劃(英語:Dynamic programming,簡稱DP)是一種在數學、管理科學、計算機科學、經濟學和生物信息學中使用的,經過把原問題分解爲相對簡單的子問題的方式求解複雜問題的方法。 動態規劃經常適用於有重疊子問題和最優子結構性質的問題,動態規劃方法所耗時間每每遠少於樸素解法。數據結構

廢話少說性能

解題

根據題意,到達網格中的某個點最短,能夠理解爲網格中的任何一個點都是能夠走過去的,並且任何一個網格都有一個最短的路徑。測試

那麼咱們使用一種數據結構保存,從頂點到達網格中任意一點的最短位置。根據人的正常邏輯,畫圖以下:spa

  • 從頂點按照行來遍歷每個位置,計算每個位置的最小路徑

根據上面的圖片能夠了解:3d

  • 處於第一行的時候,它的最短路徑就是同一行的前一個位置加上當前位置
  • 處於第一列的時候,它的最短路徑就是上一行的位置加上當前位置
  • 處於頂點的時候,它就是頂點的值
  • 位於中間的位置,它是其上一行或上一列的最小值加上當前的值

至此,咱們寫程序以下:code

public static int minPathSumAi(int[][] grid){
        // 特殊狀況處理
        if (grid.length == 0){
            return 0;
        }

        // 新建一個標記數組,標記到每一個位置的最短路徑
        int xLen = grid.length;
        int yLen = grid[0].length;
        int[][] markBit = new int[xLen][yLen];

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                // 初始位置
                if (i == 0 && j == 0){
                    markBit[i][j] = grid[i][j];
                }
                // 當點在第一行的位置時
                else if (i == 0){
                    markBit[i][j] = markBit[i][j-1] + grid[i][j];
                }
                // 當點在第一列的位置時
                else if (j == 0){
                    markBit[i][j] = markBit[i-1][j] + grid[i][j];
                }
                // 當點在數組的中間位置時
                else {
                    markBit[i][j] = Math.min(markBit[i-1][j] , markBit[i][j-1]) + grid[i][j];
                }
            }
        }

        return markBit[xLen-1][yLen-1];
    }
複製代碼

而後到LeetCode上測試,性能有待於提高,後續水平提升以後再想更優的方案吧,目前先理解解題方式。

image-20190320161740838

最後

程序的運行都是人控制的,在程序運行以前,確保你本身的邏輯清晰,畫圖能夠幫你理清邏輯。

參考

相關文章
相關標籤/搜索