区间调度问题
问题描述
有n项工作,每项工作分别在si时间开始,在ti时间结束。对于每项工作,你都可以选择参与与否。如果选择了参与,那么自始至终都必须全程参与。此外,参与工作的时间段不能重叠(即使是开始的瞬间和结束的瞬间的重叠也是不允许的)。
目标:参与尽可能多的工作,最多能参与多少项工作?
限制条件:
1 ≤ N ≤ 100000
1 ≤ si < ≤ ti ≤ 10^9
样例:
思路分析
① 在可选的工作中,每次都选取结束时间最早的工作。
② 在可选的工作中,每次都选取用时最短的工作。
③ 在可选的工作中,每次都选取与最少可选工作有重叠的工作。
算法一是正确的,另外两种的反例:
题解
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100000;
//开始时间和结束时间
int s[N], t[N];
//工作数
int n;
//用于对工作排序的pair数组
pair<int , int> itv[N];
int main(){
//读入数据
scanf("%d",&n);
for(int i = 0 ; i < n; i ++){
scanf("%d",&s[i]);
}
for(int i = 0 ; i < n ; i ++){
scanf("%d",&t[i]);
}
//对pair进行字典序比较
//为了让结束时间早的工作排在前面,把t存入first,把s存入second
for(int i = 0 ; i < n;i ++){
itv[i].first = t[i];
itv[i].second = s[i];
}
//排序
sort(itv,itv + n);
//tt是最后所选工作的时间
int res = 0; //答案
int tt = 0;
for(int i = 0 ; i < n; i ++){
if(tt < itv[i].second){
res ++;
tt = itv[i].first;
}
}
printf("%d\n",res);
return 0;
}
运行结果