算法(①贪心算法)

发布于:2025-09-01 ⋅ 阅读:(16) ⋅ 点赞:(0)

1. 背包问题(部分背包)

问题:你有一个容量为 W 的背包,有很多物品,每个物品都有自己的重量和价值。你可以切割物品,也就是可以只拿走一个物品的一部分。如何装背包才能使总价值最大化?

贪心策略:

计算每个物品的单位价值(价值/重量)。

将所有物品按照单位价值从高到低排序。

从单位价值最高的物品开始装入背包,直到装满为止。

为什么是贪心?

在每一步,我们都选择当前“最划算”的物品(单位价值最高),因为我们希望以最快的速度增加背包的总价值。对于部分背包问题,这个贪心策略是正确的,因为可以切割物品,总是能把价值最高的部分装进去。

注意:如果是0/1背包问题(物品不能切割,要么全拿,要么不拿),贪心算法就不适用了。因为局部最优(选择单位价值最高的物品)可能无法推导出全局最优。这种问题需要用动态规划解决。

2. 活动安排问题

问题:有一系列活动,每个活动都有开始时间和结束时间。你有一个会场,在同一时间只能举办一个活动。如何安排活动,才能使举办的活动数量最多?

贪心策略:

将所有活动按照结束时间从早到晚排序。

选择第一个活动(结束时间最早的那个)。

接着,选择下一个开始时间不早于已选活动结束时间的活动。

重复这个过程,直到没有更多活动可选。

为什么是贪心?

我们每一步都选择结束时间最早的活动。这个“贪心”选择留出了尽可能多的时间给后续的活动,使得我们可以安排更多的活动。这是典型的局部最优导向全局最优的例子。

3. 霍夫曼编码(Huffman Coding)

问题:给定一组字符和它们出现的频率,为每个字符设计一个二进制前缀码,使得总编码长度最短。

贪心策略:

将所有字符看作独立的节点,它们的频率作为权重。

在所有节点中,选择频率最小的两个节点。

将这两个节点合并成一个新的父节点,新节点的频率是两个子节点的频率之和。

将新节点放回列表中,并重复上述过程,直到只剩下一个根节点。

为什么是贪心?

在每一步,我们都“贪婪”地选择频率最小的两个字符进行合并。这个局部最优的选择确保了频率最高的字符被分配到最短的编码,而频率最低的字符被分配到最长的编码,从而使得总编码长度最短。

霍夫曼编码到底在做什么?

一句话概括:霍夫曼编码是一种压缩数据的方法。它通过给最常出现的字符分配最短的编码,给最不常出现的字符分配最长的编码,从而让整个文件变得更小。

你可以把它想象成:你是一家公司,要给员工发名片。

你公司里有 5 个部门:人事部, 销售部, 技术部, 财务部, 行政部。

你发现 销售部 的人最多,技术部 的人其次,人事部 和 财务部 的人比较少,行政部 的人最少。

为了省钱和方便,你决定给他们分配简称。你会给谁一个很短的简称(比如“销”)?当然是人最多的销售部。而人最少的行政部,即使简称长一点(比如“行管”),也没关系。

霍夫曼编码就是这个道理:“人多”的用短称呼,“人少”的用长称呼。

4. Prim 算法和 Kruskal 算法(最小生成树)

问题:在一个连通的带权图中,选择一些边,使得所有顶点都能被连接起来,并且这些边的总权重最小。

贪心策略:

Prim 算法:从任意一个顶点开始,每一步都“贪婪”地选择一条连接当前已选顶点集合和未选顶点集合的、权重最小的边。

Kruskal 算法:每一步都“贪婪”地选择一条权重最小的边,只要这条边不会形成一个环。

为什么是贪心?

这两种算法在每一步都选择当前能得到的最佳边(权重最小的边),并最终构建出一个最小生成树。局部最优的选择(选择最小权重边)能保证最终得到全局最优解(总权重最小)。


网站公告

今日签到

点亮在社区的每一天
去签到