贪心算法介绍与示例

贪心算法每次都取当前这一步里收益最大的选择,并且之后不再反悔。我用活动安排和分数背包两个能保证最优的例子,把选择规则和 Python 实现写出来。

贪心算法把问题拆成一串选择。每一步只看当前信息,取这一步里收益最大的那个,选完就固定,后面的步骤在剩下的问题里继续。它能得到全局最优,需要两件事同时成立:当前这一步的最优选择可以安全地留在最终答案里,而且剩下的子问题仍然是同一类问题。

活动安排和分数背包满足这两点,所以下面的写法就是最优解。硬币凑整只在币值成套(例如 1、5、10、25)时,每次先拿最大面额才是最优;币值不成套时,这个规则会选错。

活动安排

有若干活动,每个活动占一段连续时间,同一时刻只能进行一个。目标是安排尽可能多的场次。

正确的贪心是:每次选结束最早、并且不和已选活动重叠的那场。结束越早,留给后面的空档越长。按结束时间排序后扫一遍即可。

def select_activities(activities):

chosen = \[\]

end = float("-inf")

for start, finish, name in sorted(activities, key=lambda item: item1):

if start >= end:

chosen.append(name)

end = finish

return chosen

activities = [

(1, 4, "A"),

(3, 5, "B"),

(0, 6, "C"),

(5, 7, "D"),

(3, 9, "E"),

(6, 10, "F"),

(8, 11, "G"),

(8, 12, "H"),

(2, 14, "I"),

(12, 16, "J"),

]

print(select_activities(activities))

输出是 ['A', 'D', 'G', 'J'],共 4 场。时间线是 1--4、5--7、8--11、12--16。C 虽然开始得早,但一直占到 6,会挤掉 A 和 D,所以按结束时间它不会被优先选中。

排序是 O(n log n),随后一次扫描是 O(n)。

分数背包

背包容量有限,每件物品可以只拿一部分,价值按拿走的比例计算。目标是总价值最大。

贪心规则是:优先拿单位重量价值最高的物品,当前这件还能装下多少就拿多少。因为可以拆分,把容量让给单价更高的物品始终更划算。

def fractional_knapsack(items, capacity):

taken = \[\]

total = 0.0

remain = capacity

ranked = sorted(items, key=lambda item: item0 / item1, reverse=True)

for value, weight, name in ranked:

if remain <= 0:

break

portion = min(1.0, remain / weight)

taken.append((name, round(portion, 2), round(value * portion, 2)))

total += value * portion

remain -= weight * portion

return taken, round(total, 2)

items = (60, 10, "a"), (100, 20, "b"), (120, 30, "c")

print(fractional_knapsack(items, 50))

三件物品的单价分别是 6、5、4。容量 50 时先整件拿走 a、b,剩下 20 的容量再拿走 c 的 2/3。结果是:

(('a', 1.0, 60.0), ('b', 1.0, 100.0), ('c', 0.67, 80.0), 240.0)

总价值 240。物品必须整件拿走时,这个「按单价装填」的规则不再保证最优,那种 0-1 背包要用动态规划。

怎么判断能不能用贪心

写之前先回答两个问题:

  1. 把当前这一步的选择固定下来以后,剩下的最优解接上去,整体仍然最优吗?
  2. 每一步的比较标准是否只依赖当前状态,不需要回头修改?

两个答案都成立,就按这个标准排序或扫描。活动安排的标准是结束时间,分数背包的标准是单位价值。证明不了第 1 点时,这一步的局部最优可能把后面的更好方案堵死,这时改用动态规划或搜索。

相关推荐
-dzk-1 小时前
【多维动态规划】LC 64.最小路径和
算法·动态规划
垆边人似月.2 小时前
华为机试题 :字符串压缩
算法·华为
ggb喔2 小时前
52pojie 的图片工具:为什么无损转换后体积涨了 6 倍、照片方向还是歪的
图像处理·python·算法·计算机视觉·图形渲染·媒体
菜鸟~noob2332 小时前
【电子战】第25篇:自由空间、双射线与菲涅尔区【含matlab代码】
开发语言·算法·matlab
地平线开发者3 小时前
地平线征程6M YOLOv8s 部署
算法·自动驾驶
Run_Teenage3 小时前
算法:Manacher(马拉车)算法、中心扩展算法
算法
Tisfy3 小时前
LeetCode 0301.删除无效的括号:二进制枚举 / 回溯
算法·leetcode·字符串·题解·回溯·括号匹配·二进制枚举
Nil2083 小时前
leetcode 322零钱兑换
算法·leetcode·职场和发展
海绵宝宝转agent3 小时前
2026-10-9 leetcode100刷题+面经整理
笔记·算法·面试