题目链接:https://www.acwing.com/problem/content/910/
解题思路:
这道题的实现方法和前面AcWing 905. 区间选点 一模一样。
但是对于代码的解释不同。
我们还是向上一道题那样,首先对区间进行排序。
然后我们第一次选的区间是排序后的第一个区间。
为什么这样选呢。
因为我们想要得到最大的区间数;假设我们第一次选的这个区间不是最优的就表示,存在一种选法在不选最后一个区间的前通下能够多选一些区间;如果存在的话,这种方案下,我们node[n]可以被分成多个区间,也就是说,这种方案的最右边的区间的右端点一定在node[n]里,并且左端点一定大于node[n]的左端点,但是这是不存在的。因为我们排需之后node[n]这个区间的左端点已经是最大的端点了,所以 通过反证法,我们得出一定存在一个最优解里包含node[n]这个区间。
这里理解之后,我们就不断的往前去遍历,如果node[i]区间的右端点小于当前记录的值tmp,就更新tmp,直到i = 1为止。(tmp最开始为:node[n].l)
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
struct Node {
int l, r;
}node[maxn];
inline bool cmp(Node a, Node b) {
if(a.l == b.l) a.r < b.r;
return a.l < b.l;
}
int main(void) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%d%d", &node[i].l, &node[i].r);
sort(node + 1, node + 1 + n, cmp);
int ans = 1, tmp = node[n].l;
for(int i = n - 1; i >= 1; i --) {
if(node[i].r >= tmp) continue;
else {
ans ++;
tmp = node[i].l;
}
}
printf("%d\n", ans);
return 0;
}
总结:
感觉贪心好多都是需要我们倒着来想并通过反证法来证明自己思路的正确性,有一种逆向思维的感觉。