题目描述
现在各大 oj 上有 nn 个比赛,每个比赛的开始、结束的时间点是知道的。
yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。
所以,他想知道他最多能参加几个比赛。
由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 22 个及以上的比赛。
输入格式
第一行是一个正数n,接下来n行每行是2个整数ai,bi,表示比赛开始时间,结束时间。
输出格式
一个整数最多参加的比赛数目。
输入输出样例
输入
3
0 2
2 4
1 3
输出
2
做题思路
相当于就是在数轴上画区间,只要两个区间没有重叠的部分就ok。
如何判断两个区间没有重复,就是判断前一个区间的末尾有没有小于后一个区间的开始。这样比较关系出来后就需要进行排序,但是是按照开始时间排还是结束时间排,这是一个问题,因为我刚开始想的是按照开始时间排序,很不幸,全wa。
先来分析下为什么不能能按照开始时间排序,举个例子
1 10000
2 1000
3 100
4 10
如果按照开始时间进行排序,就是上边的顺序,但是从头开始遍历,判断前一个的结束是否大于等于后一个的开始,如果这样判断,就一场比赛也参加不了。但是如果按照结束时间开始排序,这样就是
4 10
3 100
2 1000
1 10000
将第一个的结束时间设置为最小的结束时间,从第二个开始判断,如果后面的开始时间大于等于前面的结束时间,就表示这个比赛可以参与,就把后面的结束时间设置为最小的结束时间。
上代码:
for(int i=1;i<n;i++) {
if(list.get(i).begin>=minOver) {
minOver=list.get(i).over;
cnt++;
}
}
接下来就是完整的解题代码
import java.util.*;
public class Main {
static class Time {
int begin;
int over;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
ArrayList<Time> list=new ArrayList<>();
for(int i=0;i<n;i++) {
Time time=new Time();
time.begin=sc.nextInt();
time.over=sc.nextInt();
list.add(time);
}
int cnt=1;
list.sort((o1,o2)->o1.over-o2.over);
int minOver=list.get(0).over;
for(int i=1;i<n;i++) {
if(list.get(i).begin>=minOver) {
minOver=list.get(i).over;
cnt++;
}
}
System.out.println(cnt);
}
}
有些人可能疑惑这里sum的初始值为什么是1,因为就算看起来这些时间都有重合,最少都能参加一场比赛
总结
选择不相交区间问题
经典的贪心题
贪心的策略是先给所有的区间按照右边界排序
其中一定要选择第一个区间