问题描述
数轴上有 n 个闭区间 。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)
Input
第一行1个整数N(N<=100)
第2~N+1行,每行两个整数a,b(a,b<=100)
Output
一个整数,代表选点的数目
Sample Input1
2
1 5
4 6
Sample Output1
1
Sample Input2
3
1 3
2 5
4 6
Sample Output2
2
解题思路
首先对于一个线段而言,如果你的整个空间是从左向后选点的话,那一定是选择线段的右端点。假设要选点的区间是
,你选择的第一个点是
,当
尽量靠右的时候,剩余区间
会最短。
那我们应该先选择哪个线段的右端点呢?也就是说,这些线段的排序规则如何?
我们选择的点是线段的右端点,而我们默认选点是在空间中从左向后选点,所以肯定要把右端点最小的排在左边。那么我们的排序规则就是右端点从小到大排序(我看到有的博客中提到当右端点相同时,左端点从大到小排,其实并没有必要)。选中一个点后,我们将包含这个点的线段都在序列中删除(或者说跳过这些线段不选点),然后选择下一个右端点。
完整代码
//#pragma GCC optimize(2)//比赛禁止使用!
//#pragma G++ optimize(2)
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn=100+1;
struct Interval
{
int a,b;
}len[maxn];
int n,ans,temp=INT_MIN;
bool comp(Interval a,Interval b)//排序原则:按照b从小到大排序
{
return a.b<b.b;
}
int getint()
{
int x=0,s=1;
char ch=' ';
while(ch<'0' || ch>'9')
{
ch=getchar();
if(ch=='-') s=-1;
}
while(ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*s;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for (int i=1; i<=n; i++)
cin>>len[i].a>>len[i].b;
sort(len+1,len+n+1,comp);
for (int i=1; i<=n; i++)
{
if(len[i].a<=temp)//当前区间含有被已经选中的点
continue;
else {//当前区间没有已经选中的点,选一个新的点
temp=len[i].b;
ans++;
}
}
cout<<ans<<endl;
return 0;
}