线段和点(贪心算法)
此次题解是借鉴的,网友的题解很不错,我只不过为了大家便于理解添了几个图罢了,主要目的我是为了加深印象,在博客上存个电子笔记。如果有不对的,还望大家不吝赐教,抱拳了!
来源:https://www.cnblogs.com/fx1998/p/12726119.html
题目描述:
有n个点和m个区间,点和区间的端点全部是整数,对于点a和区间[b,c],若a>=b且a<=c,称点a满足区间[b,c]。
求最小的点的子集,使得所有区间都被满足。
输入格式
第一行两个整数n m
以下n行 每行一个整数,代表点的坐标
以下m行 每行两个整数,代表区间的范围
输出格式
输出一行,最少的满足所有区间的点数,如无解输出-1。
思路:
1.首先说一下题意,当时我做这个题的时候,读题就读了好多遍才理解它所要表达的意思,就是用尽可能少的点去表示所有的区间,也就是说如果一个点被多个区间同时包含,那么这个点,就可以代表这些包含它的所有区间。
举个例子:点为3,区间为[1,6],[2,8],[3,9], 3这个点同时在这三个区间里,这样我只要取3这个点,就可以“代表”这三个区间。换个角度来看,也就是说我们要找到它们多个区间的公共部分,这些公共部分所涉及到的区间越多越好,因为越多,所需要的点数就越少
2.这道题巧妙之处我认为是,通过结构体对区间进行排序,比如区间为[start,end],按照end从小到大排序,end相同时,按照start从大到小排序,这样排序会使的,有多个包含关系的区间中,最里面的哪个区间在最前面。
通过画图更形象的表达这一感觉:比如排序后的区间为:[3,3],[3,4],[2,5],[2,7],[6,9]
通过图片不难看出,在不考虑[6,9]的情况下(因为与它关联的区间相对较少),剩下的这些区间中,当取这些区间的右边最小,左边最大时,不难找到最集中的区间在哪里,因此通过对结构体的排序,会使得一个点如果满足在排序后的第一个区间,就会同时满足后面的多个区间,[6,9]其实也是一样,如果他被多个区间所包围,那么只要满足它,就可以满足它后面的多个区间,这个用例只是区间太少没体现出来
3.排序之后,就是让每一个点对应每一个区间去遍历一下,看看哪个点涉及到的区间最多,记录下区间的个数,点的个数也加一个(无需记录点是哪个,只记录有几个这样的点,依次累加,最后的点数即为所求),之后再循环并且不再考虑之前涉及到的那些区间,直到所有的区间都涉及到为止
#include <bits/stdc++.h>
using namespace std;
const int maxx = 10010;
struct node{
int s; //start,区间的左端点
int e; //end,区间的右端点
} p[maxx]; //区间数组
bool cmp(node n1, node n2) {
if (n1.e != n2.e) {
return n1.e < n2.e;
}
return n1.s > n2.s;
}
int a[maxx]; //存储点
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) { //n个点
cin >> a[i];
}
for (int i = 0; i < m; i++) { //m个区间
cin >> p[i].s >> p[i].e;
}
sort(p, p+m, cmp);
int k, i, j, st = 0;
for (k = 0; k < n; k++) { //表示点的个数-1,因为是从0开始的
int _max = -1;
for (i = 0; i <= n; i++) { //遍历所有点
for (j = st; j < m; j++) {
if (p[j].s > a[i] || p[j].e < a[i]) {
break;
}
}
if (j > _max) { //看这个点最多可以满足多少个区间。
_max = j;
}
}
st = _max; //下次开始的时间就在上一次点的地方开始,寻找满足的点
if (st == m) { //所有的线段满足了,就直接退出。
break;
}
}
if (k == n) {
cout << -1 << endl;
} else {
cout << k+1 << endl;
}
return 0;
}
再分享一个小知识,#include“sstream”文件头下的一个重要用法:数字转字符串\字符串转数字
#include"iostream"
#include"sstream"
using namespace std;
int main()
{
stringstream ss;
int a = 0;
string s = "99"; // 字符型 "99" 转为 int型 99
ss << s;
ss >> a; // a此时已转换为int型99
cout << a + 1; // 输出为100
return 0;
}
“看到你们的朴实纯真,谁还不鄙视浮躁圆滑;看到你们的高洁志趣,谁还不鄙视精致利己;看到你们对弱者的尊重,谁还不鄙视强者的骄横?”