题目要求:找出覆盖线段T所需的最少区间数目
首先,将所有结束时间 <T开始时间(左侧) 以及 所有开始时间>T结束时间(右侧) 的区间排除掉
分析:
例题:
即:农夫分配N头牛工作,他把一天分成T个时间段,每头牛只在1~T之间的某些时间段工作
需要我们找出:能够完成1~T时间段内工作,所需最少的牛的数量(即相当于:找出覆盖线段(起点1,终点T)所需的最少区间)
输入:
第一行(两个数):牛总数N 总时间段T(即相当于需要覆盖线段的结束点)
接下来N行(每行两个数):即每头牛工作的开始时间、 结束时间
输出:
所需的最少牛数(即相当于所需的最少区间数)
import java.util.Arrays;
import java.util.Scanner;
public class Main {
/* 思路:相当于:找能覆盖线段L所需的最少线段数
* (1)与之前一样,将每个线段的起点和终点封装在对象中,并进行排序。
* 与之前不同的是,先对起点进行排序,如果起点不同,再对终点排序。因为需判断备选线段的起点是否小于线段L的当前起点,不然无法覆盖
* (2)
*/
public static void main(String[] args) {
//(1)输入相关数据
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();//总的线数目
int T = sc.nextInt();//需匹配线段的终点
Task[] task = new Task[n];
for(int i=0;i<n;i++) {//输入每个线段的起点和终点
task[i] = new Task(sc.nextInt(),sc.nextInt());
}
//排序
Arrays.sort(task);
//(2)遍历每一个线段,寻找所需的线段数目
int start=1;//初始时start=1,end=1,当前已有线段1
int end=1;
int ans=1;
for(int i=0;i<n;i++) {//遍历线段task[i]
int s = task[i].s;
int e = task[i].e;
if(s<=start) {//当前线段的开始时间s 小于 线段L当前的开始时间start,更新右端点end
end=Math.max(e, end);
}else {//当前线段的开始时间s 大于 L当前开始时间start
start=end+1;//更新start
ans++;//开始加入新的线段
if(s<=start) {//当前最小开始时间 < L当前开始时间start
end=Math.max(e, end);
}else {//没有合适的线段
break;
}
}//else
if(end>=T) {//已找完覆盖线段L的所有线段
break;
}
}//for
if(end<T) {//无解
System.out.println(-1);
}else {
System.out.println(ans);
}
}
}
class Task implements Comparable<Task>{
int s;//开始时间
int e;//结束时间
public Task(int s, int e) {
super();
this.s = s;
this.e = e;
}
@Override
public int compareTo(Task other) {
int x = this.s-other.s;
if(x==0) {//结束时间相等
return this.e-other.e;
}else {
return x;
}
}
}