贪心算法介绍
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择 。
1.找零问题
问题
代码及解释
# 找零问题
t = [100,50,20,5,1]
t.sort(reverse=True) # 将纸币逆序存储
def change(t,n):
# 建立一个和与t相对应的 纸币张数列表,初始为0
m = [0 for _ in range(len(t))]
# 哈希遍历
for i,money in enumerate(t):
m[i] = n//money
n = n%money
print(n)
return m,n
376元 用3张100,1张50,1张20,1张5块,1张1块,余数是0
2.分数背包
分数背包和0-1背包的做法是有区别的,两种不能混为一谈
0-1背包详见:https://blog.csdn.net/lijiamingccc/article/details/123673506
问题
这里需要注意几点:
1.商品只有一个,拿走就没了
2.拿最后一个商品的时候,容量不够,可以拿部分(分数)
3.先按照单位价值降序排序,优先拿单位价值高的
代码
goods = [(60,10),(100,20),(120,30)] # 每个商品元组表示(价格 重量)
goods.sort(key=lambda x:x[0]/x[1],reverse=True) # x[0]/x[1] 是单位价格 先拿单位价格最重的
def fractional_backpack(goods,w):
m = [0 for _ in range(len(goods))] #每种物品拿了多少个
total_v = 0
for i,(price,weight) in enumerate(goods):
if w >= weight:
m[i] = 1
total_v += price
w -= weight
else:
m[i] = w/weight
total_v += m[i] *price
w = 0
break
return total_v,m
print(fractional_backpack(goods,50))
最大价值为240 1个10 1个20 2/3个30
3.最大数字拼接问题
问题
代码
# 数字拼接问题
li = [32,94,728,7286,6,71]
li = list(map(str,li))
from functools import cmp_to_key
def xy_cmp(x,y):
if x+y < y+x:
return 1 #交换
elif x+y >= y+x:
return -1 #不交换
def number_join(li):
li.sort(key=cmp_to_key(xy_cmp))
return "".join(li)
print(number_join(li))
4.活动选择问题
问题
安排哪些活动能够使该场地举办的活动最多
最先结束的活动一定是最优解的一部分
论证部分,可以不看
代码
def activity_selection(a):
res = [a[0]] # 最早结束的活动一定是最优解的一部分
for i in range(1,len(a)):
if a[i][0] >= res[-1][1]: #当前活动的开始时间>=入选的最后一个活动中的结束时间
# 活动时间不冲突
res.append(a[i])
return res
print(activity_selection(activities))