leetcode-64-Minimum Path Sum 动态规划

问题

题目:[leetcode-64]

思路

动态规划的本质还是分治那一套,上来先划分子问题。然后考虑原问题与子问题的关系,是不是有最有子结构,是不是有重叠子问题的性质。从而进一步判断是否用动态规划。
1. 状态定义:

dp[i][j][i,j]

2. 转移函数:
dp[i][j]=min(dp[i1][j],dp[i][j1])(1)

3. 初始化:第一行第一列,因为他们只能来自于左侧和上方。
4. 打表

这个题和三角形最短路径的题目本质时一个题。换了个图形罢了。

代码(c)

int minPathSum(int** grid, int gridRowSize, int gridColSize) {

    if(!grid || gridRowSize < 0 || gridColSize < 0)
        return -1;


    int** dp = (int*)malloc( gridRowSize * sizeof(int*) );
    if(!dp)
        return -1;
    for( int i = 0; i < gridRowSize; ++i )
    {
        dp[i] = (int)malloc( gridColSize * sizeof(int) );
        if( !dp[i] )
            return -1;
    }

    dp[0][0] = grid[0][0];
    for( int i = 1; i < gridColSize; ++i )
        dp[0][i] = dp[0][i-1] + grid[0][i];
    for( int i = 1; i < gridRowSize; ++i )
        dp[i][0] = dp[i-1][0] + grid[i][0];

    for( int i = 1; i < gridRowSize; ++i )
    {
        for( int j = 1; j < gridColSize; ++j )
        {
            dp[i][j] = ( dp[i-1][j] < dp[i][j-1] )?dp[i-1][j] + grid[i][j]:dp[i][j-1] + grid[i][j];
        }
    }
    int ans = dp[gridRowSize - 1][gridColSize - 1];

    for( int i = 0; i < gridRowSize; ++i )
    {
        free(dp[i]);
    }        
    free(dp); 

    return ans;
}

代码(c++)

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        if(!grid.size())
            return 0;
        int m = grid.size();
        int n = grid[0].size();

        // 状态定义 - dp[i][j]表示从[0,0]到[i,j]的最短路径
        std::vector< std::vector<int> > dp( m, std::vector<int>( n, int() ) );

        // 初始化
        dp[0][0] = grid[0][0];
        for( int i = 1; i < m; ++i ){
            dp[i][0] = grid[i][0] + dp[i-1][0];
        }
        for( int i = 1; i < n; ++i ){
            dp[0][i] = dp[0][i-1] + grid[0][i];
        }

        // 状态转移
        for( int i = 1; i < m; ++i ){
            for( int j = 1; j < n; ++j )
            {
                dp[i][j] = grid[i][j] + min( dp[i-1][j], dp[i][j-1] );
            }
        }

        // 返回结果
        return dp[m-1][n-1];
    }
};

思路1(搜索)

当然,最朴素的办法,搜索一遍即可。结果也是显然的TLE。

代码1

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        if(!grid.size()) return 0;
        else return dfs( grid.size()-1, grid[0].size()-1, grid );

    }
private:
    // dfs(i,j)从[0,0]到[i,j]的最短路径
    int dfs( int i, int j, vector<vector<int>>& grid){
        if(!i&&!j)
            return grid[0][0];
        else if(!i)
            return grid[i][j] + dfs(i, j - 1, grid);
        else if(!j)
            return grid[i][j] + dfs(i-1, j, grid);
        else
            return grid[i][j] + min( dfs(i,j-1, grid), dfs(i-1, j, grid) );
    }
};

思路2(记忆化搜索)

对于上面的代码做修正,增加记忆化的过程。

代码2

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        if(!grid.size()) return 0;

        std::vector< std::vector<int> > dp( grid.size(), std::vector<int>(grid[0].size(), 0) );

        return dfs( grid.size()-1, grid[0].size()-1, grid, dp );

    }
private:
    // dfs(i,j)从[0,0]到[i,j]的最短路径
    int dfs( int i, int j, vector<vector<int>>& grid, vector<vector<int>>& dp){
        // 有记忆
        if( dp[i][j] > 0 )
            return dp[i][j];

        // 无记忆 - 记忆化搜索 
        if(!i&&!j)
            return dp[i][j] = grid[i][j];
        else if(!i)
            return dp[i][j] = (grid[i][j] + dfs(i, j - 1, grid, dp));
        else if(!j)
            return dp[i][j] = (grid[i][j] + dfs(i-1, j, grid, dp));
        else
            return dp[i][j] = (grid[i][j] + min( dfs(i,j-1, grid, dp), dfs(i-1, j, grid, dp)));
    }
};

你可能感兴趣的:(leetcode-64-Minimum Path Sum 动态规划)