贪心算法: 区间分组
c++
区间分组
/*
问题描述:
给定 N 个闭区间 [ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
输入格式:
第一行包含整数 N,表示区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式:
输出一个整数,表示最小组数。
数据范围:
1 ≤ N ≤ 105,
−10^9 ≤ ai ≤ bi ≤ 10^9
解题思路:
区间按照左端点排序。然后,我们按照 1->n 遍历数组(最短点是依次增大的)
对于 i
我们假设当前已经存在 x 组区间,这些 x 组的区间,每组最靠右的区间为 [left_1, right_1], ..., [left_x, right_x]
根据我们的区间左端点排序,可知 segments[i].first > 任意 left_t, t属于[1, x]闭区间,也就是说,我们需要查看 right 的情况,判断 区间 i 是否可以放入集合中
倘若存在任意一个 right_j 严格小于 segments[i].first,则可以插入,否则需要增加一个新的区间集合。
倘若存在 right_j 个区间,我们需要选择哪一个呢?答案是任意一个,因为 segments[i].first <= segments[i+1].first,
这里面的任何一个区间对于剩下的 segments集合都是 ok 的。
但是,当然是选取最小的一个好了,因为使用堆维护,非常方便
证明可以通过替换法来证明,不过需要每次需要替换一整个后面的序列,由任何一个解交换为同样最优的解题思路给出的解。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
const int N = 100010;
typedef pair<int, int> PII;
PII segments[N];
int n;
bool cmp(const PII &t1, const PII &t2) {
return t1.first <= t2.first;
}
int solution_one() {
int res = 0;
priority_queue<int, vector<int>, greater<int> > pque;
sort(segments + 1, segments + n + 1, cmp);
for (int i = 1; i <= n; i ++ ) {
if (pque.empty() == true) {
pque.push(segments[i].second);
res += 1;
} else if (pque.top() < segments[i].first) {
pque.pop();
pque.push(segments[i].second);
} else {
pque.push(segments[i].second);
res += 1;
}
}
return res; // pque.size();
}
int main()
{
// input
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
scanf("%d%d", &segments[i].first, &segments[i].second);
}
int res = solution_one();
printf("%d\n", res);
return 0;
}