洛谷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;
}
posted @ 2025-07-23 10:04  2789617221guo  阅读(46)  评论(0)    收藏  举报