完全背包问题--动态规划求解--通俗易懂--Python3

题目描述:

给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。(结果可能会很大,你需要将结果模上1000000007)

示例1:

输入: n = 5
输出:2
解释: 有两种方式可以凑成总金额:
5=5
5=1+1+1+1+1

示例2:

输入: n = 10
输出:4
解释: 有四种方式可以凑成总金额:
10=10
10=5+5
10=5+1+1+1+1+1
10=1+1+1+1+1+1+1+1+1+1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析

我们要凑成i元的硬币种类,如题目所示 coins[1 , 5 , 10 ,25]

动态规划: 对于i元,硬币的组合数目有多少种,取决于当前这枚硬币拿与不拿的情况( 最重要的思路)。

我们创建一个dp数组来储存当前情况下的最大组合数
且 dp = dp[1] + dp[0] * n

coins[] -->为空 dp[i] = 0
把1作为选择–> **coins[1]**如果我拿这枚硬币,那么dp[i] = dp[i-1]
如果不拿这枚硬币,dp[i] = 0 (无法完成组合)
所有的target都只有一种组合。此时dp[i] = dp[i-1] + dp[i] = 1

conis[1,5]
对于dp[i] 如果选择拿 ’5‘那么 dp[i] = dp[i-5]
如果不拿 那么 dp[i] -->只包含硬币’1‘的 组合数
dp[i] = d[i-5] +dp[i] (实时更新dp[i]的值)
在这里插入图片描述
其实说了这么多,总结来说就
对于一个coins列表,先对其进行遍历,对于每个新的coin,有两种选择,拿与不拿,
拿 --> dp[i-coin]
不拿 --> dp[i] (不包含当前coin的所有组合数)
dp += dp[i-coin]

每次遍历之后,将其组成target的所有组合数更新至dp[i],

def waysToChange(self, n: int) -> int:
    coins = [1, 5, 10, 25]
    #初始化dp数组
    dp = [1] + [0] * n
    for coin in coins:
        for i in range(coin, n + 1):
            dp[i] += dp[i - coin]
    return dp[n] % (10 ** 9 + 7) 
    

总结

对于背包问题,其实多做就可以很容易理解了,dp动态规划是一个很方便,效率也很高的处理复杂问题的方法,希望对你有帮助,点个赞或者收藏一波也不是不行~

你可能感兴趣的:(完全背包问题--动态规划求解--通俗易懂--Python3)