zoukankan      html  css  js  c++  java
  • 动态规划——最短路径

    一、问题描述

    在做LeetCode的时候遇到了都动态规划的问题,在维基百科中动态规划是这样解释的:

    通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最佳子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

    二、解决

    求解的的方法包括下面的两种:

    ①自顶向下的备忘录法 

    ②自底向上

    求解的过程方法:

    在求解的过程中,我们首先需要确定求解的状态转移方程

    例1:

    斐波拉切数列求解的状态转移方程:

    # 状态方程
    f(n) = f(n-2) + f(n-1)

    例2:

    问题描述,出自LeetCode第64题:https://leetcode-cn.com/problems/minimum-path-sum/

    给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
    
    说明:每次只能向下或者向右移动一步。

    代码:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int minPathSum(vector<vector<int>> &grid); // 最小路径和
    
    int main() {
        vector<vector<int >> grids = {
                {1, 3, 1},
                {1, 5, 1},
                {4, 2, 1}
        };
        cout << minPathSum(grids);
    }
    
    // 最小路径和
    int minPathSum(vector<vector<int>> &grid) {
        int m = grid.size();
        int n = grid[0].size();
        vector<vector<int>> nums(grid.size(), vector<int>(grid[0].size(), 0));
        for (int l = 0; l < grid.size(); ++l) {
            for (int i = 0; i < grid[0].size(); ++i) {
                if (l == 0 && i == 0) {  // 如果是初值就为0
                    grid[l][i] = grid[l][i];
                    continue;
                } else if (l == 0) {  // 如果在上边界就只能从前面的路径得到
                    grid[l][i] = grid[l][i] + grid[l][i - 1];
                } else if (i == 0) {  // 如果是下边界就只能从上面的结果得到
                    grid[l][i] = grid[l - 1][i] + grid[l][i];
                } else { grid[l][i] = min(grid[l - 1][i], grid[l][i - 1]) + grid[l][i]; }
            }
        }
    
        for (int k = 0; k < grid.size(); ++k) {
            for (int i = 0; i < grid[0].size(); ++i) {
                cout << " " << grid[k][i];
            }
            cout << endl;
        }
        return grid[m - 1][n - 1];
    }

    三、总结

    动态规划有一个需要理解的地方就是:在这个题中,他的表并不是代表路径,而只是代表到当前位置的最小路径和,可能这个路径的结果不是最优的,并且结果很大,但是在我们最后的时候就会把它给排除掉,保证最后的总路径一定是最优的。然后就是多练一些题就可以很熟悉解法了。如果需要路径那么我们就可以倒退结果,确定当前的结果是来自哪个最短路径,这样就可以找到最短路径了。

    可以参考题解中的一个精选题解还有一个解释过程很形象。可以帮助理解。

    四、参考

    可以参考下面的一些还不错的文章,有详细的解释:

    知乎:

    https://zhuanlan.zhihu.com/p/91582909

  • 相关阅读:
    点击退出 防止回退
    AngularJS select中ngOptions用法详解
    git hub
    .ashx datatable转excel
    写日志 log 到文件夹
    easyui layout 布局title
    easyui tree 折叠节点
    转json using指令
    Qt QWindow转QWidget
    CEF 重写弹窗事件
  • 原文地址:https://www.cnblogs.com/future-dream/p/13543076.html
Copyright © 2011-2022 走看看