题目描述:
数轴上有 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
个人思路:
既然是区间,那么必然是a,b构成一个数据,所以说我觉得用结构体要比数组强。既然是选择尽量少的点,我是先将区间按照b的第一升序,a的第二降序排序,这里用的是set存的,其自带的排序功能很好的解决了排序问题。
在选点时,选点的规则是:选择第一个区间的右端点为第一个点,之后,选择不能满足条件的第一个区间的右端点为第一个点,直到结束。
数据结构:
struct zone {
int a, b;//左右端点
zone() {};
zone(int& x, int& y) {
a = x; b = y;
}
bool operator<(const zone& q)const {//重载 <
return b != q.b ? b<q.b : a>q.a;
}
};
set<zone> s_ab;//存放有序的区间序列
int n, //区间个数
num = 1;//选点数
具体代码:
#include<iostream>
#include<set>
using namespace std;
struct zone {
int a, b;
zone() {};
zone(int& x, int& y) {
a = x; b = y;
}
bool operator<(const zone& q)const {
return b != q.b ? b<q.b : a>q.a;
}
};
set<zone> s_ab;
int n, num = 1;
zone findf(zone q1,zone q2) {
while (1) {
if (q1.b < q2.a) {
s_ab.erase(q2);
num++;
return q2;
}
s_ab.erase(q2);
if (s_ab.empty())break;//begin()不会判断set是否为空
q2 = *s_ab.begin();
}
return q1;
}
void greedyme() {
zone f = *s_ab.begin();
s_ab.erase(f);
if (s_ab.empty())break;//begin()不会判断set是否为空
zone s = *s_ab.begin();
while (1) {
if (s_ab.empty())break;//begin()不会判断set是否为空
f = findf(f, s);
if (s_ab.empty())break;//begin()不会判断set是否为空
s = *s_ab.begin();
}
}
int main() {
cin >> n;
int x, y;
for (int i = 0; i < n; ++i){
cin >> x >> y;
s_ab.insert(zone(x, y));
}
greedyme();
cout << num << endl;
return 0;
}