跳转到内容

活动选择问题

来自代码酷

活动选择问题(Activity Selection Problem)是贪心算法中的经典问题之一,旨在从一组竞争同一资源的活动中选出最大兼容子集(即不重叠的活动集合)。该问题广泛应用于调度优化领域,如会议安排、课程表制定等场景。

问题描述[编辑 | 编辑源代码]

给定一组活动 S={a1,a2,,an},每个活动 ai 有开始时间 si 和结束时间 fi(假设 fi>si)。若两个活动 aiaj 满足 [si,fi)[sj,fj)=,则称它们是兼容的。目标是找到最大的兼容活动子集。

示例输入[编辑 | 编辑源代码]

假设有以下活动集合(已按结束时间升序排列):

活动列表
活动 开始时间 结束时间
a₁ 1 3
a₂ 2 5
a₃ 4 7
a₄ 6 9
a₅ 8 10

贪心算法解法[编辑 | 编辑源代码]

贪心算法的核心思想是:**每次选择结束时间最早的活动**,以留出更多时间给剩余活动。步骤如下: 1. 将活动按结束时间升序排序。 2. 选择第一个活动,并记录其结束时间。 3. 遍历后续活动,若其开始时间 ≥ 当前结束时间,则选择该活动并更新结束时间。

伪代码[编辑 | 编辑源代码]

  
def activity_selection(start, finish):  
    selected = []  
    n = len(start)  
    i = 0  
    selected.append(i)  # 选择第一个活动  
    for j in range(1, n):  
        if start[j] >= finish[i]:  
            selected.append(j)  
            i = j  
    return selected

代码示例[编辑 | 编辑源代码]

以下为Python实现及输出:

  
start = [1, 2, 4, 6, 8]  
finish = [3, 5, 7, 9, 10]  
selected = activity_selection(start, finish)  
print("Selected activities:", selected)  # 输出: [0, 2, 4]
    • 输出解释**:

- 选择活动 a₁(时间 1–3),结束时间为 3。 - 跳过 a₂(与 a₁ 重叠),选择 a₃(4–7)。 - 跳过 a₄(与 a₃ 重叠),选择 a₅(8–10)。

可视化流程[编辑 | 编辑源代码]

gantt title 活动选择过程 dateFormat HH axisFormat %H section 选择 a₁ : 1, 3 a₃ : 4, 7 a₅ : 8, 10 section 跳过 a₂ : 2, 5 a₄ : 6, 9

正确性证明[编辑 | 编辑源代码]

贪心选择性质:每次选择局部最优解(最早结束的活动)能导向全局最优解。 - 假设存在一个最优解不包含最早结束的活动 a1,则可用 a1 替换该解中的第一个活动,仍保持兼容性且解大小不变。

实际应用[编辑 | 编辑源代码]

1. **会议室调度**:在一间会议室中安排最多会议。 2. **CPU任务调度**:优化任务执行顺序以最大化吞吐量。 3. **教育课程表**:避免课程时间冲突。

变种与扩展[编辑 | 编辑源代码]

- **加权活动选择**:每个活动有权重,目标是最大化总权重(需用动态规划解决)。 - **资源约束**:多个资源(如多间会议室)时的扩展问题。

练习[编辑 | 编辑源代码]

尝试对以下活动集合求解最大兼容子集:

活动 开始时间 结束时间
A 5 9
B 1 2
C 3 4
D 0 6
    • 答案**:选择 B(1–2)和 C(3–4)。

模板:贪心算法