动态规划例题详解(一)

本文详细介绍了动态规划的解题思路,通过斐波那契数列和最小花费爬楼梯两个经典例题,阐述了动态规划的五步解题法:确定dp数组含义、动态转移方程、初始化、遍历顺序及推导过程。同时提供了相应的Java实现,帮助读者深入理解动态规划的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划例题详解一

斐波那契数列(入门)

题目:
原题

解题思路:
1.确定dp数组下标含义
2.确定动态转移方程
3.确定dp数组初始化
4.确定遍历顺序
5.举例推导遍历dp

解题代码:

/***动态规划五步走:
    1.确定dp数组下标含义
    2.确定动态转移方程
    3.确定dp数组初始化
    4.确定遍历顺序
    5.举例推导遍历dp
    时间复杂度O(n)
 */
class Solution {
    public int fib(int n) {
        //1.确定dp数组下标含义,下标i就是当前是i的F(i)
        int[] dp=new int[n+1];

        //2.确定动态转移方程:题目中明确给出:F(n)=F(n-1)+F(n-2):故dp[n]=dp[n-1]+dp[n-2]
        //3.确定起始点,显然要得出F(n),就要先得出F(n-1)和F(n-2),依次可知F(0)和F(1)是起点,遍历顺序也可知了
        
        //特判:
        if(n==0) return 0;
        
        dp[0]=0;
        dp[1]=1;
        for(int i=2;i<=n;i++){
            //根据上述条件列出状态转移方程
            dp[i]=dp[i-1]+dp[i-2];
        }
        //返回F(n)--dp[n]
        return dp[n];
    }
}

使用最小花费爬楼梯(入门+)

题目:

在这里插入图片描述
这一题似乎就比斐波那契数列难一些了,因为题目有些许绕口,一开始我陷入了无法理解题目甚至是误解题意的意思了,若这题看得有点懵杯,可以先去看leetcode70题,本题是在它的基础上加多一些难度

我们依旧按照五步走来解这道题目:

这里一开始我脑子没转过来,因为题目要求的是到楼顶的最低消费,这里的cost[i]只是附加条件,并不是动态规划的dp数组
1.确定dp数组含义和其下标i的含义:dp[i]是指第i阶阶梯
2.确定动态转移方程:得到dp[i]只能有两种途径:dp[i-1]和dp[i-2] 如何判断是哪个阶梯上来的呢? 注意题目所需要的是最低消费,所以:dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i]:因为第i阶阶梯对应的是cost[i]的体力而不是i-1或i-2的体力
3.确定初始化dp:从上述条件我们可以轻易推出: dp[0]=cost[0] dp[1]=cost[1]
4.确定数组的遍历方向:爬至楼顶,当然是选择顺序遍历啦,从低到高进行遍历
5.举例推导遍历dp(自己在控制台打印输出)

这里贴出相应代码,供读者参考讨论:

class Solution {
    /***动态规划:
    这里一开始我脑子没转过来,因为题目要求的是到楼顶的最低消费,这里的cost[i]只是附加条件,并不是动态规划的dp数组
    1.确定dp数组含义和其下标i的含义:dp[i]是指第i阶阶梯
    2.确定动态转移方程:得到dp[i]只能有两种途径:dp[i-1]和dp[i-2]  如何判断是哪个阶梯上来的呢?
    注意题目所需要的是最低消费,所以:dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i]:因为第i阶阶梯对应的是cost[i]的体力而不是i-1或i-2的体力
    3.确定初始化dp:从上述条件我们可以轻易推出: dp[0]=cost[0]  dp[1]=cost[1]
    4.确定数组的遍历方向:爬至楼顶,当然是选择顺序遍历啦,从低到高进行遍历
    5.举例推导遍历dp
     */
    public int minCostClimbingStairs(int[] cost) {
        int n=cost.length;
        int[] dp=new int[n];
        dp[0]=cost[0];
        if(n==1){
            //特判:只有一阶阶梯,只能通过这个阶梯才能跳上去
            return dp[0];
        }
        dp[1]=cost[1];
        for(int i=2;i<n;i++){
            dp[i]=Math.min(dp[i-1],dp[i-2])+cost[i];
        }
        //阶梯顶有两种方式可以到达,即数组末两位,返回它们中的小值
        return Math.min(dp[n-1],dp[n-2]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Astronaut_001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值