题目大意
你有n个工作,同一时刻只能做一个任务,其中每个工作有其所需时间及完成的截止时间,问要完成所有工作,最迟要从什么时候开始。你最早可以从时间0开始工作。
输入格式
第一行一个整数n,表示任务数量,接下来M行,每行两个整数,Ti,Si,分别表示该任务的持续时间和截止时间。
输出格式
输出一个整数,表示最晚的开始时间,如果不能完成,输出-1.
样例输入
4
3 5
10 13
5 20
样例输出
2
分析
这道题有两种方法,一种是二分,一种是贪心,先说二分,阅读题目可知答案具有单调性,所以二分l,r,且使得l=-5,若可以完成,则r=mid,否则l=mid,制约条件是l+1
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct node{
int a,b;
}al[100001];
bool cmp(node x,node y){
if(x.b==y.b) return x.a<y.a;
return x.b<y.b;
}
int main(){
int l=-10,r,mid,n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&al[i].a,&al[i].b),r=max(r,al[i].b);
sort(al+1,al+1+n,cmp);
while(l+1<r){
mid=(l+r)/2;
int ed=mid,q=1;
for(int i=1;i<=n;i++){
if(ed>al[i].b){
q=0;
break;
}
ed+=al[i].a;
if(ed>al[i].b){
q=0;
break;
}
}
if(q)l=mid;
else r=mid;
}
if(l<0){
cout<<-1<<endl;
return 0;
}
printf("%d\n",l);
return 0;
}
再说贪心,贪心的来想,若使开始时间最晚,则要最后一个任务在最最后一刻完成,按任务完成时间降序排序,从后往前推,当发现再某一时间节点时完成不了任务,则输出-1,否则知到推结束,再输出时间节点。
上代码
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct node{
int a,b;
}al[100001];
bool cmp(node x,node y){
if(y.b==x.b) return x.a<y.a;
return x.b>y.b;
}
int n,ed=0;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&al[i].a,&al[i].b);
ed=max(ed,al[i].b);
}
sort(al+1,al+1+n,cmp);
for(int i=1;i<=n;i++){
if(ed>al[i].b) ed=al[i].b;
ed-=al[i].a;
if(ed<0){
printf("-1\n");
return 0;
}
}
printf("%d\n",ed);
return 0;
}