Python算法入门day9——贪心算法

【贪心算法的定义】

贪心算法(又称贪婪算法)是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的是在某种意义上的局部最优解

贪心算法并不保证会得到最优解,但在某些问题上贪心算法的解就是最优解。要会判断一个问题是否用贪心算法来计算。

【问题一:找零问题】

【题目描述】

假设商店老板需要找零n元钱,钱币的面额有:100元、50元、20元、5元、1元,如何找零使得所需要的钱币的数量最少?

【题目思路】

就是首先找最大的面额的能输出几张,剩下最小的金额,再找第二大的面额的能输出几张,依次类推

首先找整除且数量最少的最大面额,再找剩下的能被整除且数量最少的最大面额,依次类推

【代码运算】

t=[100,50,20,5,1] #没有从大到小排序,需要先排序
def change(t,n): #n表示找零的金额
    m=[0 for i in range(len(t))] #用于存放t里的金额都用了几张
    for i,money in enumerate(t):
        m[i]=n//money #最大面额的纸张能用的最大张数
        n=n%money #剩下的金额
    return m,n
print(change(t,376))#([3, 1, 1, 1, 1], 0)

【问题二:背包问题——分数背包求解】

【题目描述】

一个小偷在某个商店发现有n个商品,第i个商品价值vi元,中wi千克。他希望拿走的价值尽量高,但它的背包最多只能容纳W千克的东西。他应该拿走哪些商品?

【解决方案】

1. 0-1背包:对于一个商品,小偷要么把它完整拿走,要么留下。不能只拿走一部分,或把一个商品拿走多次(贪婪算法暂时先不考虑这种方法)

2.分数背包:对于一个商品,小偷可以拿走其中任意一部分。

【代码实现】

首先以单价价值更高的商品进行排序,能拿走的全拿走,到最后不能拿走的就拿走一部分,结束

li=[(60,10),(100,20),(120,30)] #商品价值和重量
li.sort(key=lambda x:x[0]/x[1],reverse=True) #根据商品的单价来排序
#print(li)
def fenshu_backpack(li,w):#w是背包的容量
    m=[0 for i in range(len(li))] #用于存放装的东西
    total_v=0 #获取的总价
    for i,(price,weight) in enumerate(li):
        if w>=weight:
            m[i]=1 #1表示全拿完
            total_v+=price
            w-=weight
        else:
            m[i]=w/weight
            total_v+=(m[i]*price)
            w=0
            break
    return m,total_v
print(fenshu_backpack(li,50)) #([1, 1, 0.6666666666666666], 240.0)

【问题三:活动选择问题】

【题目描述】

假设有n个活动,这些活动要占用同一片场地,而场地在某一时刻只能供一个活动使用。

每个活动都有一个开始时间si和结束时间fi,表示活动在[si,fi)区间占用场地。

问:安排哪些活动能够使得该场地举办的活动的个数最多?

【贪心结论】

最先结束的活动一定是最优解的一部分。

证明:假设a是所有活动中最早结束的活动,b是最优解中最先结束的活动。

        1.如果a=把,结论成立

        2.如果a不等于b,则b的结束时间一定晚于a的结束时间,则此时用a替换掉最优解中的b,a一定不与最优解中的其他活动时间重叠,因此替换后的解还是最优解。

然后依次类推,在剩下的时间里再找最早结束的解。。。

【代码运算】

#全部活动的开始时间和结束时间
active=[(1,4),(3,5),(0,6),(5,7),(3,9),(5,9),(6,10),(8,11),(8,12),(2,14),(12,16)]
#按照活动的结束时间进行排序

def active_selected(active):
    #首先将active列表中最早结束的活动保存
    res=[active[0]]
    #遍历后面的活动
    for i in range(1,len(active)):
        #如果活动的开始时间小于上一个活动结束的时间
        if active[i][0]>=res[-1][1]:
            res.append(active[i])
    return res
print(active_selected(active)) #[(1, 4), (5, 7), (8, 11), (12, 16)]

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值