预备知识
贪心算法是指:在每一步求解的步骤中,它要求“贪婪”的 选择最佳操作,
并希望通过一系列的最优选择
,能够产生一个问题的(全局的
)最优解。
贪心算法每一步必须满足一下条件:
1、可行的:即它必须满足问题的约束
2、局部最优:他是当前步骤
中 所有可行选择中最佳的局部选择
3、不可取消:即选择一旦做出,在算法的后面步骤就不可改变了<一旦在当前选择某个方案,接下来就不可撤销该方案>
题目
实例1: 贪心算法实现钱币找零问题 假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4,c5, c6张。 现在要用这些钱来支付K元,至少要用多少张纸币?
CODE
注意:程序无法处理异常情况,当身上的钱没有足够的面额来支付
solution1
"""
用贪心算法的思想,很显然,每一步尽可能用面值大的纸币即可
"""
# 钱币面值从小到大排列好的
values = [1, 5, 10, 20, 50, 100] # 钱币面值
counts = [4, 3, 2, 1, 4, 2] # 钱币张数
# 计算找零 442 元时需要各种面值多少张
def change(money):
values_ = values[::-1] # 反转,倒序, 面值最大排在前面
counts_ = counts[::-1] # 反转,倒序
result = []
for index, value in enumerate(values_):
# 需要最大面值人民币张数
c = min(money//value, counts_[index]) # splendid
# 计算剩余钱数
money -= (c * value)
result.append(c)
return result[::-1]
if __name__ == '__main__':
for i, v in enumerate(change(442)):
if v:
print('需要', v, '张', values[i] , ' 元')
solution2
for i in range(1, len(values)+1):
# min()第一个参数加入int(),防止兑换的面额有 毛 单位,例如5毛钱
c = min(int(money // values[-i]), counts[-i])
if c: # 判断钱币张数是否为0
money -= c * values[-i]
result.append(c) # 最终可以使用zip函数绑定
if not money:
return False # 身上的钱币不够 or 没有足够的面额
else:
return result[::-1]
测试
0.5//0.5
1.0 # float
# 当剩余面额的张数可以完全抵扣时,这种方法不错
money %= v