📜  用动态规划理解硬币找零问题(1)

📅  最后修改于: 2023-12-03 15:40:55.338000             🧑  作者: Mango

用动态规划理解硬币找零问题

什么是硬币找零问题

硬币找零问题,即为在支付时,需要找出一定金额的零钱。例如,在一个商场购物,商品总价为78元,你给了100元,那么商家就需要找你22元的零钱。这个问题的限制条件是,要用最少的硬币来找零。

怎么解决硬币找零问题

硬币找零问题可以用动态规划的方法来解决。在动态规划过程中,我们使用一个数组D来表示从0开始到n元钱,所需要使用的最少硬币数。则D[0] = 0,因为找0元钱不需要零钱。

假设当前硬币种类数量为m种,则DP策略为:

$$D[i]=min{D[i-c_j]+1}(j=0,1,2,...,m-1,i\geq c_j)$$

其中,c_j表示第j枚硬币的面值,i表示当前凑出的金额,D[i-c_j]表示凑够i-c_j元需要使用的最少的硬币数。因为我们需要遍历所有硬币的面值,所以j从0到m-1。

整个过程可以理解为,在调整当前凑出的金额i时,对于每一枚硬币,我们都计算出当前金额加上这个硬币时,所需的最少硬币数,然后对这些最少硬币数取最小值即可。

一个简单的Python实现
def coin_change(coins, amount):
    # 初始化D数组
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0
    # 从1元钱到amount元钱进行遍历
    for i in range(1, amount + 1):
        # 对所有的硬币进行遍历
        for coin in coins:
            # 如果当前硬币面值小于等于当前金额需要找到最少硬币的面值,则计算使用当前硬币的最少硬币数
            if coin <= i:
                dp[i] = min(dp[i], dp[i-coin] + 1)
    return dp[amount] if dp[amount] != float('inf') else -1

在上述实现中,coins表示硬币的面值,amount表示需要找零的金额。我们初始化D数组为一个长度为amount+1的全是无穷大的数组,因为我们要找到最小值,一开始全部赋为无穷大;然后,我们从1开始遍历到amount,对于每一个金额,我们再遍历所有的硬币面值,如果当前硬币的面值小于等于当前金额,我们计算使用当前硬币所需最少硬币的数量,取最小值,最后返回D数组中amount位置的值即可。

总结

硬币找零问题是一个很常见的问题,可以用动态规划的方法来解决。在程序中,我们使用D数组来记录从0开始到要找零的金额所需要使用的最少硬币数。通过枚举硬币的面值,计算出包含当前面值硬币的最少硬币数,最终得到D[amount]位置的值,即为答案。