前言
贪心算法在解决问题时总想着用当前看来最好的方法来实现。其不从整体最优上考虑问题,仅考虑某种意义上的局部最优来求解问题。贪心算法的有点是:当面对范围比较大的问题时,能产生整体最优解或整体最优解的近似值。
贪心算法的存在问题
- 不能保证最后的解是最优的。
- 不能用来求最大解或者最小解问题。
- 只能求满足某种约束条件的可行解的范围。
贪心算法的基本思路
- 建立数学模型来描述问题。
- 把求解的问题分解成若干个子问题。
- 对每一子问题求解,得到子问题的局部最优解。
- 把子问题的局部最优解合并成原来问题的一个解。
实现算法基本过程
- 从问题的某一初始解出发。
- while能向给定总目标前进一步。
- 求出可行解的一个解元素。
- 由所有解元素组合成问题的一个可行解。
案例
解决“找零”问题
假设只有1分,2分,5分,1角,2角,5角,1元面值的硬币。在超市结账找零时,收银员希望将最少的硬币数找给顾客,那么给定找零的零钱数目,如何求得最小的硬币数 ?
def look():
d=[0.01,0.02,0.05,0.1,0.2,0.5,1.0] #存储每种硬币的面值
d_num=[] #存储每种硬币的数量
s=0 #拥有零钱的总钱
temp=input('请输入每种零钱的数量(以空格为区分)')
d_num0=temp.split(' ')
for i in range(0,len(d_num0)):
d_num.append(int(d_num0[i]))
s+=d[i]*d_num[i] #计算收银员需要多少钱
sum=float(input('请输入需要找的零钱'))
if sum >s: #待找零钱数大于已有钱数
print("数据有误")
return 0
s=s-sum #柜台剩余钱数
#要想用的硬币数量最少,需要利用所有面值最大的硬币,因此从数组的最大面值开始遍历
i=len(d)-1
while i>=0:
if sum >=d[i]:
n=int(sum/d[i])
if n >=d_num[i]: #如果现有该面值硬币数小于所需要的该面值硬币数
n=d_num[i] #更新n
sum-=n*d[i] #贪心算法的关键步骤,令sum动态改变
print("用了%d个%f枚硬币"%(n,d[i]))
i-=1
if __name__ == '__main__':
look()
解决“汽车加油”问题
一辆汽车加满油后可行驶n千米,旅途中有若干个加油站,指出应在哪些加油站停靠加油,使沿途加油次数最少。对于给定的n(<=5000)千米和(k<1000)个加油站位置,计算最少加油次数?
def greedy():
n=100
k=5
num=0 #加油次数
d=[50,80,39,60,40,32] #表示加油站之间的距离
for i in range(k):
if d[i]>n:
print("没有解决方案")
i,s=0,0 #s表示距离,进行迭代
while i<=k:
s +=d[i]
if s>=n:
#当局部和大于n时,则将局部和更新为当前距离
s=d[i]
#贪心算法意在让每一次加满油后尽可能跑的更远
num+=1
i+=1
print(num)
if __name__ == '__main__':
greedy()
总结
1.贪心算法的核心:不从整体最优上考虑问题,仅考虑某种意义上的局部最优来求解问题。
2.建立数学模型来描述问题。
扫描下方二维码,关注公众号,即可免费领取学习资源,每周都有更新!