区间贪心_选择不相交的多个区间

点击查看代码
/*
给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两没有交集
输入样例:
4 1 3 2 4 3 5 6 7
//4个区间:(1,3) (2,4) (3,5) (6,7)

输出样例:
3
//有3个不相交开区间:(1,3) (3,5) (6,7)

解题思路:
1、当有多个开区间时,为了使两两区间没有交集,前一个区间右端点要小于后一个区间的左端点
2、假设I1区间在I2区间内,此时要选择范围更小的I1区间(即左端点大的那个区间),因为选择范围小的区间可以选出更多个不重叠的区间
3、读取输入的开区间数据后,对区间进行排序,先按左端点从大到小排序,当左端点相同时,右端点小的在前(即区间范围小的排在前,在后续选择过程中优先被选择)
	设置lastX记录上一个被选中区间的左端点(初始化为排序后的第1个区间,它的优先级第一),遍历剩余的待选区间,如果当前待选区间右端点小于lastX,
	那么这两个区间两两不重叠,当前待选区间符合要求可以选择,将lastX的数据更新为新选择区间的左端点,继续检查剩余的待选区间
*/
#include<cstdio>
#include<algorithm>
using namespace std;
#pragma warning(disable:4996)
const int maxn = 110;
struct Interval {
	int x, y; //开区间左右端点
}I[maxn];

bool cmp(Interval a, Interval b) {
	if (a.x != b.x) return a.x > b.x; //先按左端点从大到小排序
	else return a.y < b.y; //左端点相同时,右端点小的在前
}

int main() {
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d%d", &I[i].x, &I[i].y);
	}
	sort(I, I + n, cmp); //对n个区间按端点大小排序

	//ans记录不相交区间个数,lastX记录上一个被选中区间的左端点
	int ans = 1, lastX = I[0].x; //初始化第1个区间的左端点
	for (int i = 1; i < n; i++) { //遍历剩余n-1个区间
		if (I[i].y <= lastX) { //待选区间右端点在上一个被选中区间左端点的左边,则符合要求
			ans++; //不相交区间个数加一
			lastX = I[i].x;	//将新选择的区间左端点作为新的lastX				
		}
	}
	printf("%d\n", ans);
	return 0;
}
posted @ 2022-09-30 22:54  zhaoo_o  阅读(17)  评论(0编辑  收藏  举报