洛谷P2920 [USACO08NOV] Time Management S 题解
本题做法
- 二分答案,贪心。
思路
我们在读入数据后首先要将任务序列按照 \(s\) 升序排序,因为我们需要优先完成时间紧迫(即完成时间靠前)的任务。随后我们可以开始进行二分答案了。令左边界 \(l=-1\),右边界 \(r=\max{s}\)。对于每一次二分出来的 \(mid\) 使用 check 函数检测是否合法。
check 函数原型为 bool check(int mid),传入的 \(mid\) 就是二分出来的 \(mid\)。定义一个变量 \(now\) 表示当前时刻,初始值为 \(mid\)。遍历任务数组,先将 \(now\) 加上当前任务的耗时 \(t\),然后判断:若 \(now>s\),则代表超时了,直接 return 0。最后遍历结束还没返回值的话就代表当前的 \(mid\) 是合法的,就 return 1。
在 main 函数的二分循环中,若 check(mid) 返回值为真,则将 \(l\) 设为 \(mid\)(因为我们需要让最小值尽可能的大);否则将 \(r\) 设为 \(mid\)。
最后特判一下,若 \(l=-1\),则代表根本无法在规定的时间内完成所有的任务,输出 \(-1\);否则输出 \(l\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const double EPS=1e-8;
const int N=1005;
struct task{
int t,s;
} a[N];
int n;
bool check(int mid){
int now=mid;
for(int i=1;i<=n;i++){
now+=a[i].t;
if(now>a[i].s) return 0;
}
return 1;
}
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin>>n;
int l=-1,r=0;
for(int i=1;i<=n;i++) {
cin>>a[i].t>>a[i].s;
r=max(r,a[i].s);
}
sort(a+1,a+1+n,[](task a,task b){
if(a.s==b.s) return a.t<b.t;
return a.s<b.s;
});
r++;
while(l+1<r){
int mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
if(l==-1) cout<<"-1"<<endl;
else cout<<l<<endl;
return 0;
}

浙公网安备 33010602011771号