python学习之动态规划

        这周写题的时候遇到了一个没有了解到的新算法--动态规划,所以之后便去学习了一下,下面我来介绍一下刚学的动态规划算法。

        动态规划是一种用于解决复杂优化问题的算法思想,核心在于将大问题分解为互相关联的子问题,并通过计算子问题的解来避免重复计算,从而高效得到原问题的最优解。

        大概可以分为五步来解决问题:1.确定问题参数 2.定义状态数组 3.初始化边界条件 4.推导状态转移方程 5.获取最终结果。

        下面是一道典型例题作为示例来讲解动态规划思想该如何应用


        你有三种硬币,分别面值2元、5元和7元,每种硬币都有足够多,买一本书需要27元,如何用最少的硬币组合起来正好付清,不需要对方找钱

        首先,确定问题参数,

在这里就是我们要求的最少硬币数量,

虽然我们现在不确定最优组合是什么,但是可以设最少需要k枚硬币,a1a2一直到ak枚硬币,加起来面值为27元。

当然一定就存在最后一枚硬币为ak,那除去ak前面的硬币面值和为27-ak。现在问题从最少多少枚硬币拼出27,变成了最少多少枚硬币拼成了27-ak。

然后确定状态方程

我们可以设  f(x)=i,i就是最少拼出面值和为x的硬币数,对于x

𝑓[𝑥]=𝑚𝑖𝑛⁡{𝑓[𝑥−2]+1,𝑓[𝑥−5]+1,𝑓[𝑥−7]+1}

初始条件和边界情况

 转移方程有两个两个问题:x-2,x-5,x-7小于0怎么办?和什么时候停止运算?

首先第一个问题就是要拼的数(y)为负数或者是一个根本拼不出来的数,比如1,那么就定义f(y)为正无穷,表示拼不出来,然后将初始条件设为f[0]=0

计算顺序

拼出x所需要的最少硬币数:𝑓[𝑥]=𝑚𝑖𝑛⁡{𝑓[𝑥−2]+1,𝑓[𝑥−5]+1,𝑓[𝑥−7]+1}

初始从f[0]=0开始,然后计算f[1]f[2]一直到f[x]

这样当算到x的时候, f[x-2] ,f[x-5] ,f[x-7]都已经算过了

每一步都是算三次,算到27是第27步,故时间复杂度是27*3,远远小于用递归方法的时间复杂度

下面是完整代码示例:

def coinChange(n):

    """

    用于计算找零的最少硬币数。

    参数n:要找零的金额

    返回值:最少硬币数量,如果无法找零,则返回-1

    """

    dp = [float('inf')] * (n + 1)  # 初始化动态规划数组

    dp[0] = 0  # 找零金额为 0 时,需要 0 枚硬币

    for i in range(1, n + 1):

        if i >= 2:

            dp[i] = min(dp[i], dp[i - 2] + 1)

        if i >= 5:

            dp[i] = min(dp[i], dp[i - 5] + 1)

        if i >= 7:

            dp[i] = min(dp[i], dp[i - 7] + 1)

    if dp[n] != float('inf'):

        return dp[n]

    else:

        return -1

n=int(input('请输入要拼的金额:'))

res=coinChange(n)

print(res)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容