问题描述 :
有n个点和m个区间,点和区间的端点全部是整数,对于点a和区间[b,c],若a>=b且a<=c,称点a满足区间[b,c]。
求最小的点的子集,使得所有区间都被满足。
输入说明 :
第一行两个整数n m
以下n行 每行一个整数,代表点的坐标
以下m行 每行两个整数,代表区间的范围
1<=n,m<=10000
0<=点和区间的坐标<=50000
输出说明 :
输出一行,最少的满足所有区间的点数,如无解输出-1。
输入范例 :
5 5
2
6
3
8
7
2 5
3 4
3 3
2 7
6 9
输出范例 :
2
完整C++代码
可能有的人一开始连题目都没看懂(我就是,想了挺久),题目的要求就是最少几个点,可以使得题目所给的区间都被满足
#include <bits/stdc++.h>
using namespace std;
const int maxx = 1e4 + 100;
struct node {
int l, r;
}lr[maxx];
// 左端点从小到大,右端点从大到小
bool cmp(node a, node b) {
if (a.l == b.l) return a.r > b.r;
return a.l < b.l;
}
void fun(int n, int m) {
// 读取数据
vector<int> point(n);
for (int i = 0; i < n; i++) {
cin >> point[i];
}
sort(point.begin(), point.end());
for (int i = 0; i < m; i++) {
cin >> lr[i].l >> lr[i].r;
}
sort(lr, lr + m, cmp);
// 用变量res表示所选择的点的个数
// 用变量start表示当前选择的res个点已经满足到第start个区间(目的是要满足所有区间)
int start = 0, res = 0;
// 如果start < m,重复从点集point中寻找到可以将start变得最大的点
while (start < m) {
int max_num = 0;
int max_index = 0;
for (int i = 0; i < point.size(); i++) {
int temp = start;
// 每次从点集point中寻找到可以将start变得最大的点(也就是使得start最靠近m的点)
while (temp < m) {
if (lr[temp].l <= point[i] && point[i] <= lr[temp].r) {
temp++;
} else {
break;
}
}
// 找到之后将start更新到当前区间
if (temp > max_num) {
max_num = temp;
max_index = i;
}
}
// 更新区间范围,res+1,将这个点从point中删除
start = max_num;
point.erase(point.begin() + max_index);
res++;
// 如果point中剩余的点为0,跳出循环
if (point.empty()) {
break;
}
}
if (start == m) cout << res << endl;
else cout << -1 << endl;
}
int main() {
int n, m;
cin >> n >> m;
fun(n, m);
return 0;
}
😋欢迎大伙私信或者评论区交流讨论😋