1.优化问题
优化问题就是为了找到某些问题的最优解。
最优:比如两个点之间有许多路径,找到最短的路径。
一个典型的优化问题:兑换最少硬币问题。就是当自动售货机找零的时候,每次找给顾客最少数量的硬币。
如果不是做最优解的话,就比较简单,就每次只找给1毛钱就行了。当然,很多人不能接受。
下面看一个实例:
假设你为一家自动售货机厂家编程序,自动售货
机要每次找给顾客最少数量硬币;假设某次顾客投进$1(1美元)纸币,买了ȼ37(37美分)的东西,要找ȼ63,那么最少数量就是:2个quarter(ȼ25)、1个dime(ȼ10)和3个penny(ȼ1),一共6个硬币。
2.贪心策略Greedy Method
人们在解决上述的这些问题的时候,发现最直观的还是贪心策略。
从最大面值的硬币开始,用尽量多的数量。有余额的时候(例如用了2个25美分,还剩下13美分,不足以再用一个25美分),再到下一最大面值的硬币,还用尽量多的数量,一直到penny(ȼ1,即最小的面额)为止。
贪心策略就是每次都试着解决问题的最大的一部分。
因为我们每次都试图解决问题的尽量大的一部分。对应到兑换硬币问题,就是每次以最多数量的最大面值硬币来迅速减少找零面值。
在现实生活中,贪心策略确实是解决大多数硬币找零问题的有效方法。贪心策略是我们能想到的最直观有效的方法,反过来,也可以说,货币的面值就是按照贪心策略来设计的。
代码如下:
# 假设最大的面值是1美元,售货机的货物价格都低于1美元,可以找零的面值有25美分,10美分和1美分。
changes = [25, 10, 1]
input_money = 100 # 投入到售货机里面的是1美元,即100美分
print('Please enter the price of the item you selected:')
selection = int(input())
change = input_money - selection
count = 0 # count 用于计算硬币的个数
for i in changes: # 从最大的面值依次向小面值找钱
while change >= 0: # 当要找的零钱数大于当前面值时
change = change - i # 计算找零后是否大于0,如果找零0大于0就代表还有可能继续用这个面值找钱,否则就要换下一个小面值了
if change >= 0: # 该面值找零后大于0,使用一个该面值的硬币
count = count + 1
else: # 该面值找零后小于0,需要使用下一个面值的硬币,把需要找零的钱还原,跳出循环,进入下一个面值
change = change + i
break
print("The amount of change is %d" % count)
3. 贪心策略失效的情况
在一个漫画中,有一个杜撰的国家叫做(ELbonia),这个古怪的国家,除了有25美分,10美分和1美分以外,还有一种21美分ȼ21的硬币。
在这个国家贪心策略就失效了,如果使用原来的贪心策略,
63 = 25 * 2 + 10 * 1 + 1 * 3 , 共 2 + 1 + 3 = 6枚硬币
但是最优的策略是,
63 = 21 * 3,共 3 枚硬币。
因此贪心策略严重依赖于货币的币值设计。
参考
本文的知识来源于B站视频 【慕课+课堂实录】数据结构与算法Python版-北京大学-陈斌-字幕校对-【完结!】,是对陈斌老师课程的复习总结
代码是我自己写的,功能比较简单