动态规划算法学习(持续更新)

本文介绍了动态规划的概念及其在解决斐波那契数列和零钱兑换问题中的应用。通过分析问题、确定状态转移方程、设置初始条件和计算顺序,展示了如何避免递归中的重复计算,优化解法,降低时间复杂度。
摘要由CSDN通过智能技术生成

动态规划是什么

动态规划(Dynamic programming,简称DP)是通过把原问题分解为相对的简单的子问题来求解复杂问题的一种方法。(来自维基百科

动态规划常常适用于有重叠子问题或最优子问题的问题,时间复杂度往往比暴力法小很多。

下面通过几个具体问题来介绍。

问题1:斐波那契数列

斐波那契数列又称兔子?数列,是指这样一个数列:1,1,2,3,5,8,13....除第1,2两项外,其他所有项都是前两项之和,现在求第n项是多少。


通过四个步骤来分析问题

1.寻找状态
寻找状态就是指将原问题分解为简单的子问题,子问题之间存在着这样或那样的联系。对于本问题来说,状态就是指第n项依赖于n-1和n-2项。
2.状态转移方程(重要!!)
在此数列中,第n项的状态依赖于第n-1和第n-2项的状态,因此状态转移方程为f(n) = f(n-1)+f(n-2)
3.初始条件和边界
我们需要找到状态转移开始或停止的地方,对于本题而言,初始条件就是n=1和n=2f(n)=1
4.计算顺序
如果我们想要得到第n项,就需要知道n-1和n-2项。以此类推,直到n=1和n=2。因为后面的值依赖于前面,因此我们需要从前往后计算。

递归解法

根据上面的分析可以写出递归解法。

#include <iostream>

using namespace std;

class Soultion {
   
public:
    int f(int n) {
   
        if (n == 1)
            return 1;
        if (n == 2)
            return 1;
        return f(n - 1) + f(n - 2);
    }
};

递归解法存在的问题

假设n=10,那么求f(10)就要知道f(9)和f(8)…依次类推,如下图所示。
斐波那契数列
可以看到在递归过程中存在很多重复计算,时间复杂度为o(2n),而动态规划要做的,就是去除这些重复计算,每个结果只计算1次并保存下来,重复利用。

动态规划解法

根据上面四个步骤的分析,可以这样写动态规划的代码。可以看到,每个f(n)都只计算了一次,时间复杂度为o(n)。

#include
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值