硬币找零问题
- 前言
- 所谓贪心算法,就是遵循某种既定原则,不断选取当前条件下最优的选择来构造每一个子步骤的解决方案,直到获得问题最终的求解。即在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,所做的仅是在某种意义上的局部最优解。
- 利用贪心算法,需要解决两个问题。
- 一是问题是否适合使用贪心算法求解,即所求解问题是否具有贪心选择性质。所谓贪心选择性质,是指应用同一规则f,将原问题变为一个相似的但规模更小的子问题,后面的每一步都是当前看似最佳的选择。这种选择依赖于已做出的选择,但不依赖于未做出的选择。从全局上看,运用贪心策略解决的问题在程序的运行过程中无回溯过程。
- 二是问题是否具有局部最优解,从而通过一个贪心标准,可以得到问题的最优解。
- 利用贪心算法解题的思路一般为:
- 建立对问题精确描述的数学模型,包括定义最优解的模型。
- 将问题分解为一系列子问题,同时定义子问题的最优解结构。
- 应用贪心算法原则可以确定每个子问题的局部最优解,并根据最优解模型,用子问题的局部最优解堆叠出全局最优解。
- 问题描述
- 对于给出的商店拥有的各种硬币的面值及其数目以及付款金额,如何计算使用最少硬币的方案?
- 问题分析
- 核心思想为消费者硬币数量有限,商店的硬币无限。因此,问题可以用如下公式描述:
- min(消费者支付硬币数量+商店找零硬币数量)
- 支付值-找零值=商品值
- 可以理解为问题的求解就是上面两个问题的最优解。
- 这里使用的贪心算法为max(消费者拥有的硬币面值-商店拥有的硬币面值)优先使用。
- 例如消费者拥有面值2元的硬币,商店拥有5分的硬币,因此max=200-5=195。上面的组合情况为200,200-5,200-10,…,5。
- 现在加入购买的商品是2元的,那么上面的组合中使用2元优先,只用一个硬币即可。假如商品是2元9角5分,上面的序列存在“100-5”的情况,这是能够使用的最大币值(贪心),就用它了,那么它是2枚硬币,即支付1元找零5分,共用了三枚硬币。
- 验证算法的贪心选择性和最优子结构性质即可证明贪心算法可以得到最优解。
- 核心思想为消费者硬币数量有限,商店的硬币无限。因此,问题可以用如下公式描述:
- 代码
-
# -*-coding:utf-8-*- d = [0.05, 0.1, 0.2, 0.5, 1, 2] d_sum = [2, 3, 4, 5, 6, 4] sum_value = 0 for i in range(len(d)): sum_value += d_sum[i] * d[i] input_value = 2.5 if input_value > sum_value: print("cannot change") else: i = 5 while i >= 0: if input_value >= d[i]: n = int(input_value/d[i]) if n >= d_sum[i]: n = d_sum[i] input_value -= n * d[i] print("使用了{}个{:.2f}".format(n, d[i])) i -= 1
-
- 运行结果
- 补充说明
- 具体代码可以查看我的Github,欢迎Star或者Fork
- 参考书《你也能看得懂的Python算法书》