按结束时间升序贪心选相容区间,求最大活动数。
OJ: roj
题目 ID: 1323
难度:入门
标签:贪心区间调度排序
创建: 2026-09-30 05:05
更新: 2026-10-05 09:42
题目描述
学校有
样例输入:
text
11 3 5 1 4 12 14 8 12 0 6 8 11 6 10 5 7 3 8 5 9 2 13样例输出:4。
思路
经典区间调度:把所有活动按结束时间升序排序后扫描,维护已选活动的最大结束时刻 last_end,凡是 begin_i >= last_end 的就贪心选上,最终统计的总数就是最大可相容活动数。
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-07-05 21:47
# update_at: 2026-07-05 21:47
import sys
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
n = next(data)
acts = sorted(
((next(data), next(data)) for _ in range(n)),
key=lambda x: x[1], # 按结束时间升序,为每次选最早结束者做准备
)
ans = 0
last_end = -1 # 礼堂上次被占用的结束时刻;begin_i 非负,-1 表示尚未使用
for begin, end in acts:
can_use = begin >= last_end # 当前活动与已安排的不冲突
if can_use:
ans += 1
last_end = end
print(ans)
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 09:42
* update_at: 2026-10-05 09:42
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1005;
ll n;
ll b[MAXN]; // b[i] 第 i 个活动的起始时间
ll e[MAXN]; // e[i] 第 i 个活动的结束时间
ll order[MAXN]; // order[i] 第 i 小的活动下标(按 end 升序)
// 比较函数:先按结束时间升序,结束时间相同时按起始时间升序。
bool cmp_by_end(ll x, ll y) {
if (e[x] != e[y]) return e[x] < e[y];
return b[x] < b[y];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (ll i = 1; i <= n; i++) {
cin >> b[i] >> e[i];
order[i] = i;
}
// 按结束时间升序排序:每次优先选结束最早的活动,留出更大后续时间窗。
sort(order + 1, order + n + 1, cmp_by_end);
ll ans = 0;
ll last_end = -1; // 已选活动中最后一个的结束时刻;begin_i >= 0,-1 表示尚未选
for (ll k = 1; k <= n; k++) {
ll i = order[k];
if (b[i] >= last_end) { // 与已选集合不相交,可选
ans++;
last_end = e[i];
}
}
cout << ans << "\n";
return 0;
}