题解:洛谷 P6244 Country Fair Events

【题目来源】

洛谷:P6244 [USACO06OPEN] County Fair Events S - 洛谷

【题目描述】

FJ 参加活动。

他想参加尽可能多的 \(N\) 个活动,参加完某个之后可以立刻参加下一个。

给定 FJ 可参加的活动列表、其开始时间 \(T\) 和持续时间 \(L\) ,求 FJ 可以参加的最大活动数。

FJ 每个活动都不会提早离开。

【输入】

第一行有一个整数 \(N\)

第二到 \(N+1\) 行:每行包含两个用空格分隔的整数 \(T\)\(L\) ,意义如上述。

【输出】

输出仅一行,FJ 最多能参加几个活动。

【输入样例】

7
1 6
8 6
14 5
19 2
1 8
18 3
10 6

【输出样例】

4

【核心思想】

  1. 问题分析:给定 \(N\) 个活动的开始时间 \(T\) 和持续时间 \(L\),求最多能参加多少个互不重叠的活动。本质上是经典区间调度贪心问题:按结束时间排序,每次选择结束最早且不与已选活动冲突的活动。

  2. 算法选择

    • 贪心排序:按活动结束时间升序排序
    • 贪心选择:维护上一个选中活动的结束时间 last,选择开始时间 \(\geq\) last 的最早结束活动
  3. 关键步骤

    • 读取数据:读入 \(N\)\(N\) 个活动的 \((T, L)\),计算结束时间 \(end = T + L\)
    • 排序:按 end 升序排列
    • 贪心选择
      • 初始化 last = p[1].endans = 0
      • 遍历 \(i = 2\)\(N\)
        • \(p[i].start \geq last\):选中该活动,ans++last = p[i].end
    • 输出 ans + 1(加上第一个活动)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N \log N)\),排序主导
    • 空间复杂度:\(O(N)\),存储活动信息
  5. 区间调度贪心的核心思想

    • 结束时间优先:选择结束最早的活动,为后续活动留出更多时间,这是区间调度问题的经典最优策略
    • 交换论证:假设最优解中第一个活动不是结束最早的,用结束更早的活动替换不会减少可选活动数
    • 不相交判定:两个活动相容当且仅当后一个的开始时间 \(\geq\) 前一个的结束时间
    • 与动态规划的对比:贪心 \(O(N \log N)\) 远优于 DP 的 \(O(N^2)\),但仅适用于"最大化活动数"目标
    • 适用于活动选择、区间调度、资源分配类问题

【解题思路】

【算法标签】

普及- #贪心

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n, ans=0;
struct node {
    int start ,end;
}p[10005];
bool cmp(node a, node b)
{
    return a.end<b.end;
}
int main()
{
    cin >> n;  // 输入n
    for (int i=1; i<=n; i++) {  // 遍历n个活动
        int tmp;
        cin >> p[i].start >> tmp;  // 记录起始时间
        p[i].end = p[i].start+tmp;  // 并计算结束时间
    }
    sort(p+1, p+n+1, cmp);  // 按照结束时间从小到大排序
    int last = p[1].end;  // 定义last为第一个活动的结束时间
    for (int i=2; i<=n; i++) {  // 从第2个活动开始遍历
        if (p[i].start>=last) {  // 如果其起始时间在上个结束时间之后
            ans++;  // 就可以参加
            last = p[i].end;  // 更新结束时间为本活动结束时间
        }
    }
    cout << ans+1 << endl;  // 输出结果,加上的1为第1个活动
    return 0;
}

【运行结果】

7
1 6
8 6
14 5
19 2
1 8
18 3
10 6
4
posted @ 2026-08-17 22:49  团爸讲算法  阅读(16)  评论(0)    收藏  举报