硬币找零问题

硬币找零问题:假设需要找零的金额为C,最少要用多少面值为p1<p2<…<pn的硬币(面值种类为n,且假设每种面值的硬币都足够多)​?

贪心算法的基本原理是:遵循某种既定原则,不断地选取当前条件下最优的选择来构造每一个子步骤,直到获得问题最终的求解。即在求解时,总是作出当前看来最好的选择

贪心选择性质是指应用同一规则,将原问题变为一个相似的但规模更小的子问题,而后的每一步都是当前看似最佳的选择。这种选择依赖于已做出的选择,但不依赖于未做出的选择。从全局来看,运用贪心策略解决的问题在程序的运行过程中无回溯过程。贪心选择性质的证明一般采用数学归纳法,证明每一步做出的贪心选择确实能导致问题的整体(全局)最优解,也有基于算法的输出,或使用一种“拟阵”结构等形式的证明。

注意,贪心算法利用问题的贪心性质,简化了分解原始问题的过程,每次只关注在当前状态下可以获得的局部最优解,通过拼接各阶段的局部最优解获得最终问题的解。因为贪心选择可以依赖于以往所做的选择,但绝不依赖于未来所做的选择,也不依赖于子问题的解。故而贪心算法往往求解时与动态规划相反,采用自顶向下的方式,迭代作出贪心选择,不断化简问题规模。

问题实例:假设要找零8元,市面上有3种不同面值的硬币,各硬币的面值分别为1元、3元、4元。

可以先使用动态规划思路进行求解:

F(C)=min{F(C-pi)}+1,C>0且C≥pi

初始条件:F(0)=0

F(1)=min{F(1-1)}+1=1;

F(2)=min{F(2-1)}+1=2;

F(3)=min{F(3-1),F(3-3)}+1=1;

F(4)=min{F(4-1),F(4-3),F(4-4)}+1=1;

F(5)=min{F(5-1),F(5-3),F(5-4)}+1=2;

F(6)=min{F(6-1),F(6-3),F(6-4)}+1=2;

F(7)=min{F(7-1),F(7-3),F(7-4)}+1=2;

F(8)=min{F(8-1),F(8-3),F(8-4)}+1=2。

因此最少需要2枚硬币即可找零8元。

当使用贪心算法在计算的时候,从最大面值的硬币开始,直接得出答案2枚4元硬币。

注意,虽然贪心算法看似非常简便迅速,但是它不总是有效的。比如,当要找零6元时,它得到的答案是1枚4元硬币和2枚1元硬币,即最少3枚硬币。而动态规划得到的正确答案是2枚3元硬币。这个时候贪心算法不再适用,应选用动态规划等其他算法进行求解。

现在假设市面上有6种不同面值的硬币,各硬币的面值分别为5分、1角、2角、5角、1元、2元,要找零10.5元,求出最少硬币的数量。

从面值最大的硬币开始遍历:

需要5枚2元硬币,剩下0.5元。

再加1枚5角硬币。

一共6枚硬币。

def getChange(coins, amount):
    coins.sort()
    # 从面值最大的硬币开始遍历
    i = len(coins) - 1
    while i >= 0:
        if amount >= coins[i]:
            n = int(amount // coins[i])
            change = n * coins[i]
            amount -= change
            amount = round(amount, 2)  # 四舍五入到小数点第2位
            print(n, '枚', coins[i])
        i -= 1
    print()

输入:

输出:

输入:

输出:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

algorithm6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值