算法-程序设计课week3---B - 区间选点(编译器选GNU G++)POJ1328

B - 区间选点(编译器选GNU G++)POJ1328

数轴上有 n 个闭区间 [a_i, b_i]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)

Input

第一行1个整数N(N<=100)
第2~N+1行,每行两个整数a,b(a,b<=100)

Output

一个整数,代表选点的数目

Examples
Input

2
1 5
4 6

Output

1

Input

3
1 3
2 5
4 6

Output

2

思路与收获
这种区间的题目最好是在纸上画一画,可以极大帮助思路的形成。

这道题可以这么理解:把这些区间比作图的节点,区间重合就是节点连同,该题所求的点数就是图的连同分量数目了。

什么情况下需要新开一个连同分量?唯一的情况就是上一个区间的终点小于下一个区间的起点,这种情况下两个区间互不重合,必须有两个点分别被两个区间覆盖。

其他的区间间相互关系要么属于上述关系,要么不属于上述关系,所有不属于上述关系的情况都不需要新开连同分量。我们可以手动画一下,就知道这样做是正确的(所以动手画太重要了)。

基本思路就是:只关注互不重合的区间,忽略那些和当前区间重合的区间。 两区间是否重合的办法就是: 上一个区间的终点小于当前区间的起点,则两个区间互不重合。 为了简化上述标准的判断,可以将所有区间按照结束位置排序

具体流程可以看代码,代码比口述流程严禁多了。

tips:画区间并不生动,有可能看走要配错括号,画线段就好多了。

#include<algorithm>
#include<cstdio>
using namespace std;
struct node {
	int a,b;
	bool operator < (node& y) {
		return
		    (b<y.b)
		    ||
		    (b==y.b&&a<y.a);
	}
};
int main() {
	//freopen("inb.txt","r",stdin);
	int n;
	scanf("%d",&n);
	
	node c[n];
	
	for(int i=0; i<n; i++)scanf("%d %d",&c[i].a,&c[i].b);

	//将区间排序,便于我们遍历
	sort(c,c+n);

	int flag=c[0].b;
	int count=1;
	//遍历所有区间
	for(auto item:c) {
		//只需关注那些互不重合的区间,忽略那些和当前区间重合的区间 
		//手动画图跑一下代码会比较好理解,画线段比画区间更形象
		//遇到右端点更右的区间的左端点,证明这个遇到了一个新的不重合的区间,因此点数加一
		if(flag<item.a) {
			flag=item.b;
			count++;
		}
	}
	printf("%d",count);
}
发布了166 篇原创文章 · 获赞 21 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/lgfx21/article/details/104737532