题目
数轴上有 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
Examples
Input
3
1 3
2 5
4 6
Output
2
思路
这道题的目的是取最少的点以使得输入的每个区间都至少含一个点。
我们将输入的区间按以下规则排序:
① 右端点的值越大越往后排
② 当右端点相同时,左端点的值越大越往后排
为了让一个点尽可能地落在多个区间内,我们应该尽量取靠后(右)的点,以使其尽可能地落在更多(排在后面)的区间中。按照这个想法,我们首先选择排在第一个区间的右端点,该点不仅落在了第一个区间中,而且是最靠后(右)的点。接着把该点落在的所有区间剔除,让剩下的区间重新排序,重复选点的过程。
以上是贪心算法的策略。这个策略之所以可行,是因为这种选点的策略总能带来最好的结果,所以贪心算法总能得到最好的结果。
下面的图可以更好地展示这个过程:
① 输入所有的区间
② 给区间排序
③ 选点
代码
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
int n;
int cnt = 0;
vector<pair<int, int>> v;
// pair<int a, int b>
bool cmp(pair<int, int> x, pair<int, int> y)
{
if (x.second != y.second) return x.second < y.second;
else return x.first < y.first;
}
bool inRange(int p, pair<int, int>s)
{
if (p<s.first || p>s.second) return false;
else return true;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++) {
int a, b;
cin >> a >> b;
v.push_back(make_pair(a, b));
}
sort(v.begin(), v.end(), cmp);
reverse(v.begin(),v.end());
int p = v.back().second;
cnt++;
while (v.size() != 0) {
pair<int, int> s = v.back();
if (inRange(p, s)) v.pop_back();
else {
p = s.second;
v.pop_back();
cnt++;
}
}
cout << cnt << endl;
return 0;
}