贪心法(CSP初级算法)

2 阅读5分钟

贪心算法的本质

每一步都选择当前看起来最优的方案。

但一定强调:

“局部最优” 不一定等于 “全局最优”。

所以:

  • 有些题能贪心
  • 有些题不能贪心

这是学生最容易混乱的地方。


给 CSP-J 初学者的推荐教学顺序

建议别一上来就讲抽象定义。

直接:

第一阶段:生活化理解(最重要)

可以举例:


例子1:买东西找零

有:

  • 100元
  • 50元
  • 20元
  • 10元

找 180 元。

我们会:

  • 先拿100
  • 再拿50
  • 再拿20
  • 再拿10

因为:

每次都先选最大的。

这就是贪心。


例子2:走一步看一步

“每次都做当前最划算的选择”

比如:

  • 每次吃最大的苹果
  • 每次选分数最高的题
  • 每次选最便宜的商品

都属于贪心思想。


第二阶段:认识经典贪心模型

建议先别上特别难的。

推荐顺序:


① 排队接水(超级经典)

思想:

让接水时间短的人先接。

因为:

  • 后面的人都会等前面的人
  • 所以前面越短越好

这是:

排序 + 贪心


能讲的知识点

  • 为什么排序后更优
  • 贪心证明的简单思想
  • sort 的使用
  • 结构体排序

② 数轴覆盖 / 区间问题

例如:

  • 最少放几个点覆盖所有区间
  • 最多不相交区间

这是 CSP-J 高频。

核心:

按右端点排序。

学生第一次会真正感受到:

“排序方式不同,贪心结果完全不同。”


③ 零钱兑换(有限情况)

讲:

  • 有些货币系统能贪心
  • 有些不能

比如:

1 5 10 20 可以。

但:

1 3 4

找6:

  • 贪心:4+1+1(3枚)
  • 最优:3+3(2枚)

这个例子特别经典。

可以让学生第一次意识到:

贪心不是万能的!


第三阶段:总结贪心套路

你可以帮学生整理:

贪心题常见信号

看到这些词要警觉:

  • 最多
  • 最少
  • 最大
  • 最优
  • 尽量
  • 优先
  • 能否

很多时候都可能是贪心。


贪心题常见步骤

第一步:观察规律

问:

当前怎么选最划算?


第二步:排序

很多贪心题:

本质就是排序。

例如:

  • 按小到大
  • 按右端点
  • 按结束时间
  • 按价值

第三步:边扫边选

通常:

for(...)
{
    if(可以选)
        选它;
}

给学生强调的重要观念

1. 贪心 ≠ 暴力尝试

贪心:

  • 不回头
  • 不后悔
  • 不搜索

2. 贪心不一定正确

所以很多题难点不是“写代码”。

而是:

“为什么这样贪心是对的?”


CSP-J阶段最经典的贪心题

推荐顺序:

  1. 排队接水
  2. 最大不相交区间
  3. 国王游戏(可后期)
  4. 货仓选址(可结合中位数)
  5. 部分背包
  6. 区间覆盖
  7. 会议安排
  8. 线段选点

你这节课建议这样安排

前20分钟

生活例子 + 贪心思想。


中间40分钟

排队接水。

重点讲:

  • 为什么短的在前
  • 排序为什么重要

后面30分钟

区间问题。

让学生感受:

“排序依据” 是贪心灵魂。


课后作业建议 “判断能不能贪心”

CSP-J 贪心算法课后作业(基础提高版)

建议:

  • 前4题必做
  • 后2题选做
  • 最后一题思考题(特别重要)

这样既不会太难,又能真正建立“贪心思维”。


第一部分:思想理解(不写代码)

1. 判断题(写“能”或“不能”)

下面的问题,能否直接使用“每次选当前最优”的贪心思想?


(1)

有:
1元、5元、10元硬币。

现在找18元。

每次优先选最大的硬币。

这种方法能得到最少硬币数吗?


(2)

有:
1元、3元、4元硬币。

现在找6元。

每次优先选最大的硬币。

这种方法能得到最少硬币数吗?


(3)

从多个活动中选择最多能参加的活动。

每次优先选择结束时间最早的活动。

这种方法是否合理?


(4)

背包容量有限。

每次优先选择价值最大的物品。

一定正确吗?


第二部分:基础贪心题(代码题)


2. 排队接水(经典)

有 n 个人接水。

每个人接水时间为:

3 1 4 2 5

要求:

(1)

设计一种排队方案。

使所有人的等待总时间最少。


(2)

输出最小等待总时间。


(3)

说明:

为什么短时间的人应该排前面?


3. 糖果分配

有 8 块糖果。

小朋友每次尽量拿:

  • 5块
  • 如果不够再拿1块

请问最少需要拿几次?


思考:

为什么这里可以贪心?


4. 最大不重叠区间(重要)

有若干活动:

1 3
2 4
3 5
0 6
5 7
8 9
5 9

每行表示:

开始时间 结束时间

要求:

选择最多互不冲突的活动。


要求:

(1)

写出你的选择方案。

(2)

说明:

为什么应该按结束时间排序?


第三部分:提高题(选做)


5. 部分背包问题

背包容量为 10。

有:

物品重量价值
A220
B530
C428

物品可以只拿一部分。


问:

怎样拿价值最大?


提示:

思考:

单位重量价值

6. 贪心排序思考题(很重要)

下面这些题目:

  • 排队接水
  • 活动选择
  • 部分背包

它们都需要排序。


请思考:

为什么:

有的题按“小到大”排序,

有的题按“结束时间”排序,

有的题按“单位价值”排序?


第四部分:算法总结(必须写)

请用自己的话总结:


1. 什么是贪心算法?


2. 贪心算法的特点是什么?


3. 贪心算法一定正确吗?

请举一个反例。


额外加分题(适合强一点学生)

有硬币:

1 7 10

现在找:

14

问:

如果每次优先选最大的硬币:

会发生什么?

最优方案是什么?


这个题能让学生彻底理解:

“局部最优 ≠ 全局最优”

非常适合 CSP-J 初学阶段。