1. 程式人生 > >[DP]矩陣的最小路徑和

[DP]矩陣的最小路徑和

其他 局限性 == vector ++ span table 獲得 方程

題目

給定一個矩陣m, 從左上角開始每次只能向右或者向下走,最後到達右下角的位置,路徑上所有的樹子累加起來就是路徑和,返回所有的路徑中最小的路徑和.

解法一

這是一道經典的動態規劃題,狀態轉移方程為dp[i][j] = min{dp[i - 1][j], dp[i][j - 1]} + m[i][j].可以用一個二維的dp矩陣來求解.對於dp矩陣,第一行和第一列只會有一種走法,就是從左到右或者從上到下的累加,所以可以先進行初始化,然後其他元素就可以用過轉移方程一個一個填充,知道把整個dp矩陣填充完畢.

解法二

如果用二維數組,對於m行n列的數組,空間復雜度就是O(m*n).動態規劃中常用的優化方法之一就是僅使用一個一維數組在進行這個叠代過程.但是這種空間壓縮也有局限性,那就是不能記錄獲得最後結果的路徑.如果需要完整路徑的話還是需要二維的動態規劃表.

代碼

#include <iostream>
#include <vector>

using namespace std;
//使用二維數組的方式
int minPathSum1(int arr[4][4], int m, int n) {
    if (m == 0 || n == 0)
        return 0;
    int dp[m][n];
    dp[0][0] = arr[0][0];
    for (int i = 1; i < m; i ++)
        dp[i][0] = dp[i - 1][0] + arr[i][0];
    for
(int j = 1; j < n; j ++) dp[0][j] = dp[0][j - 1] + arr[0][j]; for (int i = 1; i < m; i ++) { for (int j = 1; j < n; j ++) dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + arr[i][j]; } // print array // for (int i = 0; i < 4; i ++) { // for (int j = 0; j < 4; j ++)
// cout<<dp[i][j]<<" "; // cout<<endl; // } return dp[m - 1][n - 1]; } //使用一維數組的方式 int minPathSum2(int arr[4][4], int m, int n) { if (m == 0 || n == 0) return 0; int dp[n]; dp[0] = arr[0][0]; for (int k = 1; k < n; k ++) dp[k] = dp[k - 1] + arr[0][k]; for (int i = 1; i < m; i ++) { for (int j = 0; j < n; j ++) { if (j == 0) dp[j] = dp[j] + arr[i][0]; else { dp[j] = min(dp[j - 1], dp[j]) + arr[i][j]; } } } //print dp array // for (int k = 0; k < n; k ++) // cout<<dp[k]<<" "; // cout<<endl; return dp[n - 1]; } int main() { int arr[4][4] = {{1,3,5,9},{8,1,3,4},{5,0,6,1},{8,8,4,0}}; for (int i = 0; i < 4; i ++) { for (int j = 0; j < 4; j ++) cout<<arr[i][j]<<" "; cout<<endl; } cout<<minPathSum2(arr, 4, 4)<<endl; return 0; }

[DP]矩陣的最小路徑和