一、区间调度问题
题目描述
-
有n项工作,每项工作分别在si时间开始,
在ti时间结束.对于每项工作,你都可以选择参与与否.
如果选择了参与,那么自始至终都必须全程参与.此外,
参与工作的时间段不能重复(即使是开始的瞬间和结束的瞬间的重叠也是不允许的).
你的目标是参与尽可能多的工作,那么最多能参与多少项工作呢? -
1≤n≤100000,1≤si≤ti≤109
-
输入:
第一行:n
第二行:n个整数空格隔开,代表n个工作的开始时间
第三行:n个整数空格隔开,代表n个工作的结束时间 -
输出:常数(表示可参与的工作数)
算法思想
- 贪心:封装每一项工作,包括开始时间和结束时间,每次选择结束时间最早的一项工作,注意,没想工作的开始时间必须大于上一项工作的结束时间,需要设置全局变量(记录上次一工作的结束时间)
代码
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
Job[] jobs=new Job[n];
for (int i = 0; i < n; i++) {
int st=scanner.nextInt();
jobs[i]=new Job(st, 0);
}
for (int i = 0; i < n; i++) {
jobs[i].yt=scanner.nextInt();
}
solve(jobs);
}
private static void solve(Job[] jobs) {
Arrays.sort(jobs);
int count=1;
int lastChoiceJobYt=jobs[0].yt;
for (int i = 1; i < jobs.length; i++) {
if(jobs[i].st>lastChoiceJobYt) {
count++;
lastChoiceJobYt=jobs[i].yt;
}
}
System.out.println(count);
}
private static class Job implements Comparable<Job>{
int st;
int yt;
public Job(int st, int yt) {
super();
this.st = st;
this.yt = yt;
}
//按结束时间从小到大排
//结束时间一样的,按开始时间从大到小排列
@Override
public int compareTo(Job o) {
if(this.yt==o.yt) {
return o.st-this.st;
}
return this.yt-o.yt;
}
}
二、区间选点问题
题目描述
- 给定n个整数闭区间,以及他们需要命中点的数目,设计程序求出最少需要多少个点
题目解析
- 与区间调度问题类似,不过这个增加在每个区域需要固定的点数,依旧是贪心思想,每次从“结束时间”开始打点。
代码
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
Interval[] intervals=new Interval[n];
for (int i = 0; i < n; i++) {
intervals[i]=new Interval(scanner.nextInt(), scanner.nextInt(), scanner.nextInt());
}
solve(intervals);
}
private static void solve(Interval[] intervals) {
Arrays.sort(intervals);
int lastIndex=intervals.length-1;
//以最长的结尾为终点
int[] point=new int[intervals[lastIndex].bi+1];
for (int i = 0; i < point.length; i++) {
point[i]=-1;
}
for (int i = 0; i < intervals.length; i++) {
int pointNum=hasPointNum(point,intervals[i].ai,intervals[i].bi);
if(intervals[i].ci>pointNum) {
int remains=intervals[i].ci-pointNum;
for (int j = intervals[i].bi; j >= intervals[i].ai; j--) {
if (remains==0) {
break;
}
if (point[j]==-1) {
point[j]=1;
remains--;
}
}
}
}
int allCount=hasPointNum(point, 0, point.length-1);
System.out.println(allCount);
}
private static int hasPointNum(int[] point, int ai, int bi) {
int count=0;
for (int i = ai; i <= bi; i++) {
if(point[i]==1) {
count++;
}
}
return count;
}
private static class Interval implements Comparable<Interval>{
int ai;
int bi;
int ci;
public Interval(int ai, int bi, int ci) {
super();
this.ai = ai;
this.bi = bi;
this.ci = ci;
}
//区间起点小的排前面
//起点相同的,则结尾越小越靠前
@Override
public int compareTo(Interval o) {
if (this.ai==o.ai) {
return this.bi-o.bi;
}
return this.ai-o.ai;
}
}