区间不相交问题描述:
给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两之间没有交集。
步骤:
- 将所有区间按照左端点从大到小进行排序
- 左端点相等,则按照右端点从小到大进行排序
- 总是选择左端点最大的区间(若左端点相等,则选择右端点最小的区间)
思路:
首先我们明确一点,当区间a被区间b包含时,我们一定会选择区间a,在这点的基础上我们看一个例子。
例子:
- 如图为排序后的一般情况(从上到下依次命名为I1~I5)
- 现在我们去掉区间包含的情况I2,I3(因为我们一定不会选他们,不妨忽视掉)
- 忽视掉区间包含的情况后,不难看出I1的右边一段是一定不会和其他区间重合的,即△x。
- 既然△x不影响结果,我们不妨把△x忽视掉。
- 忽视掉后,是不是发现I1被包含在I4里了呢,所以我们选出I1
结论:
我们总是优先选出左端点最大的区间!
代码实现:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <queue>
using namespace std;
const int maxn = 105;
struct Inteval // 定义结构体存放区间
{
int x, y;
}a[maxn];
bool cmp(Inteval a, Inteval b)
{
if (a.x != b.x) return a.x > b.x; // 左端点不同,则按左端点从大到小排
return a.y < b.y; // 左端点相同,则按右端点从小到大排
}
int main()
{
int n;
while (~scanf("%d", &n) & n)
{
for (int i = 0; i < n; i++)
{
scanf("%d%d", &a[i].x, &a[i].y);
}
sort(a, a+n, cmp);
// res储存不重合区间数,lastX保存上一个所选区间的左端点
int res = 1, lastX = a[0].x;
for (int i = 1; i < n; i++)
{
// 若i区间右端点小于等于lastX(即两区间不重合)
if (a[i].y <= lastX)
{
res++;
lastX = a[i].x;
}
}
printf("%d\n", res);
}
return 0;
}