python贪心算法 | 找零问题 | 分数背包 | 最大数字拼接 | 活动选择问题

贪心算法介绍

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

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))
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码魔法师!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值