【Leetcode】硬币-动态规划

感觉是我学一辈子也想不出的算法,还是记录一下吧。

  • 题目描述:

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

  • 题解:

状态转移公式:

简化过得公式就是用前 i 种硬币凑成 v 分的方法数 = 用前 i - 1 种硬币凑成 v 分的方法数 + 用前 i 种硬币凑成 v - ci 的方法数,ci 是 第 i 种硬币的面值。

然而方法竟然还能简化到只用一行大小为 n+1 的数列(记为F)来计算:注意硬币要从大到小排列,因为 本轮的 f(i, v) (即 F[v]) 是由上一轮的 f(i - 1, v) (即 F[v]) 和 本轮的 f(i, v - ci)(即F[v - ci]),所以F[v]要在F[v-ci]之前更新。

代码

class Solution:
    def waysToChange(self, n: int) -> int:
        mod = 10**9 + 7
        coins = [25, 10, 5, 1]

        f = [1] + [0] * n
        for coin in coins:
            for v in range(coin, n + 1):
                f[v] += f[v - coin]
        return f[n] % mod
  • 以 n = 25为例:

coin = 25:

v = 25: f[25] = f[25] + f[0] = 1(用25分的硬币凑成25分)

coin = 10:

v = 10: f[10] = f[10] + f[0] = 1(用10分25分硬币凑10分)

v = 11: f[11] = f[11] + f[1] = 0 (用10分25分硬币凑11分)

...

v = 20: f[20] = f[20] + f[10] = 1(用10分25分硬币凑20分)

...

v = 25: f[25] = f[25] + f[15] = 1(用10分25分硬币凑25分)

coin = 5:

i = 5: f[5] = f[5] + f[0] = 1(用5分10分25分硬币凑5分)

i = 6: f[6] = f[6] + f[1] = 0(用5分10分25分硬币凑6分)

...

i = 10:f[10] = f[10] + f[5] = 2(用5分10分25分硬币凑成10分)

i = 11:f[11] = f[11] + f[6] = 0 (用5分10分25分硬币凑成11分)

...

i = 15:f[15] = f[15] + f[10] = 2 (用5分10分25分硬币凑成15分)

...

i = 20:f[20] = f[20] + f[15] = 3

...

i = 25:f[25] = f[25] + f[20] = 4

coin = 1:

i = 1: f[1] = f[1] + f[0] = 1(用1分5分10分25分凑1分)

...

i = 5: f[5] = f[5] + f[4] = 2

...

i = 10: f[10] = f[10] + f[9] = 4

... 

i = 15: f[15] = f[15] + f[14] = 6

...

i = 20: f[20] = f[20] + f[19] = 7

...

i = 25: f[25] = f[25] + f[24} = 11

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值