贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
这么说有点抽象,来举一个例子:
例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿?
指定每次拿最大的,最终结果就是拿走最大数额的钱。
每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。
贪心的套路(什么时候用贪心)
很多同学做贪心的题目的时候,想不出来是贪心,想知道有没有什么套路可以一看就看出来是贪心。
说实话贪心算法并没有固定的套路。
所以唯一的难点就是如何通过局部最优,推出整体最优。
#找零问题
t=[100,50,20,5,1]
def change(t,n):
m=[0 for _ in range(len(t))]
for i,money in enumerate(t):
m[i]=n//money
n=n%money
return m,n
#分数背包/0-1背包
'''分数背包可以使用贪心算法解决,0-1背包不可以'''
goods=[[60,10],[120,30],[100,20]] #每个商品的(价格,重量)
def fractional_backpack(goods,w):
for i in range(len(goods)): #给每个商品添加一个原始下标元素,在排序后,m按照原始下标进行加法
goods[i].append(i)
goods.sort(key=lambda x:x[0]/x[1],reverse=True) #按照价格重量比排序
m=[0 for _ in range(len(goods))]
for (prise,weight,index) in goods:
if w>=weight:
m[index]=weight
w-=weight
else:
m[index]=w
break
return m
print(fractional_backpack(goods,50))
有n个非负数字,拼接为最大数,如 12,45,9,41 拼接为9454112
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
else:
return 0
li=[32,94,128,1286,662,66]
def number_jion(li):
li=list(map(str,li))
li.sort(key=cmp_to_key(xy_cmp))
return ''.join(li)
print(number_jion(li))
n个活动,每个户活有个开始时间和结束时间,这些活动占用同一片场地,怎样安排,可以有最大的活动数
'''
每次都找最先结束的活动
'''
activatise=[(1,4),(3,5),(0,6),(5,7),(3,9),(5,9),(6,10),(8,11),(8,12),(12,16)]
#保证按结束时间排好序
activatise.sort(key=lambda x:x[1])
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(activatise))