动态规划4

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chent86/article/details/84475499

 leetcode 63

分析:

需要注意到题目描述中:机器人只能向下或者向右移动,这一点大大降低了难度。所以可以列出转移方程:

dp[i][j]表示从起点到(i,j)的路径的数量,那么:

dp[i][j] = dp[i-1][j] + dp[i][j-1]  (当这两个点在grid之内且不为障碍物时)

另外,如果(i,j)是障碍物,dp[i][j] = 0

代码如下:

int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
    int height = obstacleGrid.size();
    if(height == 0)
        return 1;
    int width = obstacleGrid[0].size();
    vector<vector<int>> dp(height, vector<int>(width, 0));
    if(obstacleGrid[0][0] == 0)  // 起点为障碍物
        dp[0][0] = 1;
    for(int i = 0; i < height; i++)
    for(int j = 0; j < width; j++) {
        if(obstacleGrid[i][j] == 1) {
            dp[i][j] = 0;        // 目的地为障碍物
            continue;
        }
        if(i > 0 && obstacleGrid[i-1][j] != 1) {
            dp[i][j] += dp[i-1][j];
        }
        if(j > 0 && obstacleGrid[i][j-1] != 1) {
            dp[i][j] += dp[i][j-1];
        }
    }
    return dp[height-1][width-1];
}

 leetcode 64

分析:

与上一题的题型非常相似,可列出状态转移方程:

设dp[i][j]为从左上角到右下角的最短路径的长度,则:

dp[i][j] = min(dp[i-1][j], dp[i][j-1])+grid[i][j]

如果(i,j)不在gird内,dp[i][j] = INT_MAX

如果 (i-1,j),(i,j-1)都不在gird内,则dp[i][j] = grid[i][[j]

代码如下:

int minPathSum(vector<vector<int>>& grid) {
    int height = grid.size();
    if(height == 0)
        return 0;
    int width = grid[0].size();
    vector<vector<int>> dp(height, vector<int>(width, 0));
    for(int i = 0; i < height; i++)
    for(int j = 0; j < width; j++) {
        int up = INT_MAX, left = INT_MAX;
        if(i > 0)
            up = dp[i-1][j];
        if(j > 0)
            left = dp[i][j-1];
        if(i > 0 || j > 0)
            dp[i][j] = min(up, left)+grid[i][j];
        else
            dp[i][j] = grid[i][j];
    }
    return dp[height-1][width-1];
}

leetcode 120

分析:

也是求最短路径,只不过grid的形状为三角形,以及目的地不止一个,大同小异。不过可以尝试达到O(n)的空间复杂度。

设dp[i,j]为从起点到达(i,j)的最短路径,则有转移方程:

dp[i,j] = min(dp[i-1] [j-1], dp[i-1][j]) + triangle[i][j];

如果(i,j)不在grid内,则dp[i][j] = INT_MAX

如果(i-1,j-1)和(i-1,j)都不在grid内,则dp[i][j] = triangle[i][j]

然后就是两层for循环解决问题。

以上是使用二维dp数组,空间复杂度为O(n^{2}),要达到空间复杂度,首先直接把前一维i去掉,也就是每次都重复使用同一个dp数组。那么问题来了,因为后一层dp运算需要用到前一层的结果,那么在运算的过程中就不能把这些值提前覆盖了,解决办法就是:将j的循环逆向。

代码如下:

int minimumTotal(vector<vector<int>>& triangle) {
    int height = triangle.size();
    if(height == 0)
        return 0;
    int width = height;
    vector<int> dp(width, 0);
    for(int i = 0; i < height; i++)
    for(int j = i; j >= 0; j--) {
        int left = INT_MAX, right = INT_MAX;
        if(j > 0)
            left = dp[j-1];
        if(j < i)
            right = dp[j];
        if(j == 0 && i == 0)
            left = right = 0;
        dp[j] = min(left, right) + triangle[i][j];
    }
    sort(dp.begin(), dp.end());
    return dp[0];
}

猜你喜欢

转载自blog.csdn.net/chent86/article/details/84475499
今日推荐