【动态规划算法】不同路径_不同路径升级版

简介: 【动态规划算法】不同路径_不同路径升级版

动态规划五步曲

1.确定dp及dp[i]的含义

2.找出递推公式

3.确定dp数组如何初始化

4.确定遍历顺序

5.打印dp数组验证

一、不同路径

点我直达

思路:动态规划

由题意易知,dp数组需要使用二维。

  • 1.确定dp数组以及dp[i][j]的含义

dp[i][j]的含义是:到达下标i,j位置有dp[i][j]种路径

  • 2.递推公式

由题意我们可以知道,机器人只能向右走或者向下走,所以只有两种情况能走到dp[i][j]位置,如下图:

即:dp[i-1][j]往下走一步就能到达dp[i][j]位置,或者dp[i][j-1]往右走一步就能达到dp[i][j]位置。

所以到达dp[i][j]位置有:

dp[i][j] = dp[i-1][j] + dp[i][j-1]

注意这里存在一个误区:可能你会觉得
dp[i][j] = dp[i-1][j]+1+dp[i][j-1] + 1

产生这样想法的原因是你没有搞清楚dp[i][j]的含义是什么

dp[i][j]的含义是到达下标i,j位置有多少种路径,而不是走了多少步,如果是走了多少步,那么就可以从dp[i-1][j]往下+1,或者dp[i][j-1]往右+1。

  • 3.如何进行初始化

    我们知道,从dp[0][0]位置开始的第一行和第一列的任意位置,都只有一种方法能够到达。
    因为只能向右走或者向下走,比如到达dp[0][5]位置,只能有一条路径可以到达。

所以第一行和第一列的所有位置都需要初始化成1。

  • 4.确定遍历顺序
    根据题意可知,dp数组是需要从左到由从上到下遍历的。
  • 5.打印dp数组进行验证

具体代码如下:

//动态规划五步曲:
//1.确定dp[i][j] 的含义:
//到达dp[i][j] 位置一共有多少种不同路径
//2.确定递推公式
//dp[i][j] = dp[i-1][j] + dp[i][j-1];
//到dp[i-1][i]的路径量+到dp[i][j-1]的路径量。
//3.确定如何初始化
//最左边一行和最上边一行全部初始化成1,因为题目要求只能向下或者向右移动一步最上边一行到任意位置只有一种路径,最左边一行到任意位置也只有一种路径。
//4.确定遍历顺序,由题意可知,只能从左到右,从上到下进行遍历。
//5.打印dp数组的值
class Solution {
public:
    int uniquePaths(int m, int n) 
    {
        int dp[m][n];
        for(int i = 0;i<m;++i)
        {
            dp[i][0] = 1;
        }
        for(int j = 0;j<n;++j)
        {
            dp[0][j] = 1;
        }
        for(int i = 1;i<m;++i)
        {
            for(int j = 1;j<n;++j)
            {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
                printf("%d ",dp[i][j]);
            }
        }
        return dp[m-1][n-1];
    }
};

时间复杂度O(m*n),空间复杂度O(m*n)

二、不同路径(升级版)

点我直达!

思路:动态规划

大致的情况与第一题相同,只不过在路上会遇到障碍物。

有障碍物的位置为1,没有障碍物的位置为0。

但是在初始化的地方和递归的过程是有一点不同的。

在初始化时:

该情况,当我们在第一行或者第一列的初始化位置遇到障碍物时

在障碍物以及之后的所有位置,都不能被初始化,因为一旦遇到障碍物,就没有办法继续往后走了。

还有一种情况是:障碍物在起点或者终点,都无法获取路径,直接返回0即可。

所以在初始化的时候我们应该这样写代码:

//初始化有障碍物,遇到障碍物及其之后的位置不能再初始化成1了,就跳过
for(int i = 0;i < m && obstacleGrid[i][0] != 1;++i)
{
    dp[i][0] = 1;
}
for(int j = 0;j<n && obstacleGrid[0][j] != 1;++j)
{
    dp[0][j] = 1;
}

2.在进行递推时

如果我们在如图所示的地方遇到了障碍物,我们就不能再递推了,就需要直接跳过该位置。(且题目的意思,障碍物的地方路径数是0)

所以我们应该这样写代码:

for(int i = 1;i<m;++i)
        {
            for(int j = 1;j<n;++j)
            {
                if(obstacleGrid[i][j] == 1)
                    continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }

具体代码如下:

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int>> dp(m, vector<int>(n, 0));
        //初始化有障碍物,遇到障碍物及其之后的位置不能再初始化成1了,就跳过
        for(int i = 0;i < m && obstacleGrid[i][0] != 1;++i)
        {
            dp[i][0] = 1;
        }
        for(int j = 0;j<n && obstacleGrid[0][j] != 1;++j)
        {
            dp[0][j] = 1;
        }
        for(int i = 1;i<m;++i)
        {
            for(int j = 1;j<n;++j)
            {
                if(obstacleGrid[i][j] == 1)
                    continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
};

时间复杂度O(m*n),空间复杂度O(m*n)

总结

今天写了动态规划不同路径,我发现跟着b站大佬的学习视频学动态规划特别爽~

继续干动态规划!

相关文章
|
2月前
|
算法 开发者 Python
惊呆了!Python算法设计与分析,分治法、贪心、动态规划...这些你都会了吗?不会?那还不快来学!
【7月更文挑战第10天】探索编程巅峰,算法至关重要。Python以其易读性成为学习算法的首选。分治法,如归并排序,将大问题拆解;贪心算法,如找零问题,每步求局部最优;动态规划,如斐波那契数列,利用子问题解。通过示例代码,理解并掌握这些算法,提升编程技能,面对挑战更加从容。动手实践,体验算法的神奇力量吧!
60 8
|
28天前
|
算法
测试工程师的技能升级:LeetCode算法挑战与职业成长
这篇文章通过作者亲身体验LeetCode算法题的过程,探讨了测试工程师学习算法的重要性,并强调了算法技能对于测试职业成长的必要性。
42 1
测试工程师的技能升级:LeetCode算法挑战与职业成长
|
1月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
1月前
|
算法 Java 测试技术
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
这篇文章介绍了基于动态规划法的三种算法:解决背包问题的递归和自底向上实现、Warshall算法和Floyd算法,并提供了它们的伪代码、Java源代码实现以及时间效率分析。
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
|
1月前
|
算法
基于多路径路由的全局感知网络流量分配优化算法matlab仿真
本文提出一种全局感知网络流量分配优化算法,针对现代网络中多路径路由的需求,旨在均衡分配流量、减轻拥塞并提升吞吐量。算法基于网络模型G(N, M),包含N节点与M连接,并考虑K种不同优先级的流量。通过迭代调整每种流量在各路径上的分配比例,依据带宽利用率um=Σ(xm,k * dk) / cm来优化网络性能,确保高优先级流量的有效传输同时最大化利用网络资源。算法设定收敛条件以避免陷入局部最优解。
|
2月前
|
算法 Python
Python算法高手进阶指南:分治法、贪心算法、动态规划,掌握它们,算法难题迎刃而解!
【7月更文挑战第10天】探索Python算法的精华:分治法(如归并排序)、贪心策略(如找零钱问题)和动态规划(解复杂问题)。通过示例代码揭示它们如何优化问题解决,提升编程技能。掌握这些策略,攀登技术巅峰。
62 2
|
2月前
|
算法 程序员 Python
算法小白到大神的蜕变之路:Python分治法、贪心、动态规划,一步步带你走向算法巅峰!
【7月更文挑战第9天】探索算法之旅,以Python解锁编程高手之路。分治法如二分查找,将复杂问题拆解;贪心算法解决活动选择,每次选取局部最优;动态规划求斐波那契数列,避免重复计算,实现全局最优。每一步学习,都是编程能力的升华,助你应对复杂挑战,迈向算法大师!
34 1
|
2月前
|
存储 算法 Python
Python算法界的秘密武器:分治法巧解难题,贪心算法快速决策,动态规划优化未来!
【7月更文挑战第9天】Python中的分治、贪心和动态规划是三大关键算法。分治法将大问题分解为小问题求解,如归并排序;贪心算法每步选局部最优解,不保证全局最优,如找零钱;动态规划存储子问题解求全局最优,如斐波那契数列。选择合适算法能提升编程效率。
49 1
|
2月前
|
存储 算法 Python
震撼!Python算法设计与分析,分治法、贪心、动态规划...这些经典算法如何改变你的编程世界!
【7月更文挑战第9天】在Python的算法天地,分治、贪心、动态规划三巨头揭示了解题的智慧。分治如归并排序,将大问题拆解为小部分解决;贪心算法以局部最优求全局,如Prim的最小生成树;动态规划通过存储子问题解避免重复计算,如斐波那契数列。掌握这些,将重塑你的编程思维,点亮技术之路。
51 1
|
2月前
|
存储 算法 大数据
Python算法高手的必修课:深入理解分治法、贪心算法、动态规划,让你的代码更智能!
【7月更文挑战第9天】在Python算法学习中,分治法(如归并排序)将大问题分解为小部分递归解决;贪心算法(如货币找零)在每步选择局部最优解尝试达到全局最优;动态规划(如斐波那契数列)通过存储子问题解避免重复计算,解决重叠子问题。掌握这三种方法能提升代码效率,解决复杂问题。
35 1