动态规划基础——dp五部曲模板(二)

简介: 动态规划基础——dp五部曲模板(二)

4. 不同路径(LeetCode-62)


题目

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。


机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。


问总共有多少条不同的路径?


示例 1:


输入:m = 3, n = 7
输出:28


示例 2:

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下


示例 3:

输入:m = 7, n = 3
输出:28


示例 4:

输入:m = 3, n = 3
输出:6


提示:


1 <= m, n <= 100


题目数据保证答案小于等于 2 * 109


思路

五部曲继续


1.dp[m][n] 含义:到达m行n列有 dp[m][n] 条路径


2.机器人每次只能向下或向右移动,所以该点路径条数只与它上面和左边的点有关,是它们路径条数之和

d p [ m ] [ n ] = d p [ m − 1 ] [ n ] + d p [ m ] [ n − 1 ]


初始化时,最左边一列和最上面一行的值肯定为1


要先有 − 1 -1−1 才能有你,肯定正序



代码展示

class Solution
{
public:
    int uniquePaths(int m, int n)
    {
        vector<vector<int>> dp(m, vector<int>(n));
        for (int i = 0; i < m; i++)
        {
            dp[i][0] = 1;
        }
        for (int i = 0; i < n; i++)
        {
            dp[0][i] = 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];
            }
        }
        return dp[m - 1][n - 1];
    }
};


可以滚动数组优化,可以看出,我们计算是以行为单位一行一行计算的,其实该点值只和它上一行有关,所以创建一个长度为网格列数的数组

d p [ j ] = d p [ j ] + d p [ j − 1 ]


dp[j-1] 最初是欲计算点上左侧的值,被计算后,数值的含义下移,变成欲计算点左侧的值。同理 dp[j] 在计算之前代表欲计算点上侧的值

class Solution
{
public:
    int uniquePaths(int m, int n)
    {
        vector<int> dp(n);
        for (int i = 0; i < n; i++)
        {
            dp[i] = 1;
        }
        for (int i = 1; i < m; i++)
        {
            for (int j = 1; j < n; j++)
            {
                dp[j] = dp[j] + dp[j - 1];
            }
        }
        return dp[n - 1];
    }
};


5. 不同路径Ⅱ(LeetCode-63)


题目

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。


机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。


现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?


网格中的障碍物和空位置分别用 1 和 0 来表示。


示例 1:



输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右


示例 2:



输入:obstacleGrid = [[0,1],[0,0]]
输出:1


提示:


m == obstacleGrid.length

n == obstacleGrid[i].length

1 <= m, n <= 100

obstacleGrid[i][j] 为 0 或 1


思路

五部曲


1.dp[m][n] 含义:到达m行n列有 dp[m][n] 条路径


2.机器人每次只能向下或向右移动,所以该点路径条数只与它上面和左边的点有关,是它们路径条数之和。这里比先前的题多了障碍,所以障碍这点的 dp 值为零

image.png

初始化时,最左边一列和最上面一行的值肯定为1。但要注意如果有障碍,那么那点 dp 值要为零。还要注意只要有一个障碍,那它后面的值不用算了,肯定为零


要先有 − 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));
        for (int i = 0; i < m; i++)
        {
            if (obstacleGrid[i][0] == 0)
            {
                dp[i][0] = 1;
            }
            else
            {
                dp[i][0] = 0;
                break;
            }
        }
        for (int i = 0; i < n; i++)
        {
            if (obstacleGrid[0][i] == 0)
            {
                dp[0][i] = 1;
            }
            else
            {
                dp[0][i] = 0;
                break;
            }
        }
        for (int i = 1; i < m; i++)
        {
            for (int j = 1; j < n; j++)
            {
                if (obstacleGrid[i][j] == 0)
                {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
                else
                {
                    dp[i][j] = 0;
                }
            }
        }
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                cout << dp[i][j] << " ";
            }
            cout << endl;
        }
        return dp[m - 1][n - 1];
    }
};


6. 整数拆分(LeetCode-343)


题目

给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。


返回 你可以获得的最大乘积 。


示例 1:

输入: n = 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。


示例 2:

输入: n = 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。


提示:


2 <= n <= 58


思路

1.拆数字 i ,可以得到的最大乘积为 dp[i]


2.可能会是两数相乘所得,也有可能是三数及以上相乘所得。这里就分两种情况取较大值即可。


变量 i 从 1 遍历到 n-1 ,两数相乘情况下结果为 i ∗ ( n − i ) ,三数及以上相乘情况下结果为 i ∗ d p [ n − i ] 。这里的 dp[n-i] 是拆分数字 n-i 的最大乘积,其实是已经拆分过的,它就已经是几个数相加等于 n-i 的情况了,这点要理解,主要是想明白数组的含义

d p [ n ] = m a x ( i ∗ ( n − i ) , i ∗ d p [ n − i ] )


3.dp[2]=1


4.先有 dp[n-i] 再有 dp[n] ,所以从前往后


5.测试用例


代码展示

class Solution
{
public:
    int integerBreak(int n)
    {
        vector<int> dp(n + 1);
        dp[2] = 1;
        for (int i = 3; i <= n; i++)
        {
            for (int j = 1; j < i - 1; j++)
            {
                // max函数只能两两比较
                dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]));
            }
        }
        return dp[n];
    }
};
目录
相关文章
语雀的markdown常用语法
语雀的markdown常用语法
8232 0
语雀的markdown常用语法
|
存储 测试技术 区块链
阿里云、百度云及移动云对象存储横向性能对比测试
在企业的数字化转型进程中,我们观察到越来越多的公司将其IT基础设施迁移到云端。随着企业业务的持续运营,无论是储存、处理、分享还是删除,都会产生大量的数据,这就要求有一个既可靠又高效的系统来管理和存储这些信息。对象存储产品在这个场景中扮演了至关重要的角色。它们以一种可扩展、安全、持久的方式,有效地满足了对大规模非结构化数据存储的需求。 尽管市场上云计算提供商众多,各自都有自己独特的对象存储产品,面对这样的丰富选择,如何寻找最符合企业需求的产品呢?这正是企业今天寻求解答的问题。 在本篇文章中,我们将深入进行一项横向对比测试,专门对阿里云OSS、百度云BOS和移动云EOS这三大云服务提供商的对象
3608 0
|
数据可视化 数据挖掘
使用R语言进行多维缩放分析
【4月更文挑战第27天】本文介绍了R语言中的多维缩放分析(MDS)技术,用于高维数据的可视化。MDS通过映射数据点到低维空间保持距离或相似性,帮助理解数据结构。R中的`cmdscale`和`isoMDS`函数可用于构建MDS模型,而`dist`计算距离矩阵。通过实例展示了如何分析消费者对品牌评价,`stressplot`和`procrustes`函数则用于模型解释和验证。R还支持经典MDS、度量MDS和非度量MDS等高级主题,为数据探索提供强大工具。
280 0
|
弹性计算 固态存储 大数据
2024阿里云服务器租用价格表(一年/按月/按小时报价明细)
阿里云服务器2024年最新租用价格表显示,轻量应用服务器2核2G3M带宽一年82元(约6.8元/月),2核4G4M带宽轻量服务器一年298元。新老用户共享99元一年的2核2G3M带宽ECS经济型e实例服务器与199元一年的企业专享2核4G5M带宽ECS u1实例服务器优惠。4核16G10M带宽游戏服务器70元/月,8核32G10M带宽160元/月。GPU服务器如gn6v和gn6i等提供新用户专享折扣。续费折扣方面,续费一年享有7.5折,续费五年则有3折优惠。按小时计费的云服务器ECS实例中,如ecs.u1-c1m4.large(2核8G)每小时0.45元。
30675 17
|
算法 SoC
在写PWM风扇驱动之前:如何透过FG信号,获取风扇转速?
本文介绍了如何通过PWM风扇的FG信号线获取风扇转速的方法,包括风扇规格的解读、FG信号的公式推导、软件算法的解析,以及在全志H713平台上实现风扇转速获取的驱动代码示例。
1899 2
在写PWM风扇驱动之前:如何透过FG信号,获取风扇转速?
|
JavaScript 前端开发
Playwright执行 JavaScript 脚本:探索浏览器自动化的新境界
在Web自动化中,Playwright提供`page.evaluate()`和`page.evaluate_handle()`来执行JavaScript脚本。`page.evaluate()`返回脚本执行结果,而`page.evaluate_handle()`返回JSHandle。示例展示了如何使用它们,如打印网页标题、操作元素及获取页面内容。通过这些方法,可以处理常规方法难以操作的网页元素。
|
XML JSON API
如何获取阿里巴巴中国站1688商品详情 API 返回值说明
`1688` 是阿里巴巴旗下的一个 B2B(Business-to-Business)电商平台,专注于为企业提供批发和采购服务。`1688` 商品详情 API 是指从阿里巴巴中国站获取商品详细信息的接口。这个 API 通常需要开发者在阿里巴巴开放平台上注册并获取相应的 API 密钥(AppKey 和 AppSecret)才能使用。
|
JSON 自然语言处理 网络协议
【案例实战】SpringBoot整合GRPC微服务远程通信
【案例实战】SpringBoot整合GRPC微服务远程通信
【案例实战】SpringBoot整合GRPC微服务远程通信
|
机器学习/深度学习 编解码 文字识别
OCR文字识别技术总结(四)
文本识别是OCR(Optical Character Recognition)的一个子任务,其任务为识别一个固定区域的的文本内容。在OCR的两阶段方法里,它接在文本检测后面,将图像信息转换为文字信息。
1381 0
OCR文字识别技术总结(四)
|
Java 数据库 Spring
MyBatis-Plus——Mapper接口中使用自定义的CRUD方法及Mapper.xml映射文件
MyBatis-Plus——Mapper接口中使用自定义的CRUD方法及Mapper.xml映射文件
2020 0
MyBatis-Plus——Mapper接口中使用自定义的CRUD方法及Mapper.xml映射文件

热门文章

最新文章