描述
在一个数轴上有n条线段,现选取其中k条线段使得这k条线段两两没有重叠部分(端点可以重合),问最大的k为多少?
输入
第一行为一个正整数n,下面n行每行2个整数ai,bi,描述每条线段。
对于20%的数据,n≤10。
对于50%的数据,n≤1000。
对于70%的数据,n≤100000。
对于100%的数据,n≤1000000, 0≤ai<bi≤1000000。
输出
输出文件仅包括1个整数,为k的最大值。
样例输入
3
0 2
2 4
1 3样例输出
2
题目来源
https://tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=5927
举一个事例,来理解输入:
0 2
2 4
1 35 6
2 6
上图已经明了地展现了输入的意义,那么理解输入后,我们应该去思考贪心的思想。
那上图为输入,我们可以得出答案:3,即[0, 2][2, 4][5, 6]。
我们为什么先取了[0, 2]?因为它是最早结束的一条线段,只有早结束的去来了,后面才有机会去取别的线段。
所以我们可以得出贪心思想:越早结束的越优先取。
接下来上代码~
首先我们需要一个结构体 Line{}; 来记录每条线段的起点和终点。
struct Line { int s; int e; } a[1000005]; // 并定义一个数组存储线段数据
还需要写一个用于控制该结构体排序规则的函数 cmp()
**这一步不懂的没事,自定义排序一般用这个方法,背下来就可以了
bool cmp(const Line& a, const Line& b) { return a.e < b.e; // 按照终点从前往后排序 }
接着我们要处理排好序的序列,重叠部分不能算上。
int main() { /* ...... */ sort(a + 1, a + n + 1, cmp); int num = 0, lst = 0x80000000; // lst记录上一个被选用的值,由于i从1开始,所以无条件被选,故初值为0x80000000 for (int i = 1; i <= n; i++) { if (a[i].start >= lst) num++, lst = a[i].e; } cout << num << endl; return 0; }
完整代码
#include <bits/stdc++.h> using namespace std; struct Line { int s; int e; } a[1000005]; bool cmp(const Line& a, const Line& b); int main() { int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i].s >> a[i].e; sort(a + 1, a + n + 1, cmp); int num = 0, lst = 0x80000000; for (int i = 1; i <= n; i++) { if (a[i].s >= lst) num++, lst = a[i].e; } cout << num << endl; return 0; } bool cmp(const Line& a, const Line& b) { return a.e < b.e; }
温馨提示:做这种题目注意两端重叠允许不允许!
感谢您能够看到这里,点不点赞都没关系,您的支持是我最大的动力😊。