题意
一共有n个设施需要修复,给出每个设施修复需要的时长,和每个设施被修复好的最晚时间(deadline),求最多能修复好多少个设施。
题解
贪心,首先先将所有修复任务按照最晚时间由小到大排序,如果本题开始时间固定,那就直接按顺序计算即可(hdoj2037),但是因为每个设施的开始时间是弹性的,所以我们应该让每个修复任务开始时间尽量较早,故可以建立一个堆,保存每个修复的设施的修复时长,按顺序判断每个任务是否可以完成。
即:考虑第i个任务,
若满足已选择的任务所花费的时间+当前修复任务所需时间<=此任务截止时间则res+1,并将此修复任务所需时长压入堆中。
若不满足:则判断当前任务时长是否小于已选择任务中时长最长的那个,若是,则用时长较短的任务替换时长较长的任务,为后面的任务留出更充裕时间。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
vector<pii> a; //存储每个任务需要时间以及截止时间。
priority_queue<ll> pq; //大根堆存储选择任务的时长
bool cmp(pii x,pii y){ //排序方式
return x.second < y.second;
}
int main()
{
int n;
scanf("%d",&n);
a.resize(n);
for(int i = 0;i < n;++i)
scanf("%lld%lld",&a[i].first,&a[i].second);
sort(a.begin(),a.end(),cmp); //按截止时间排序
int res = 0; //当前以选择任务
ll now = 0; //当前已选择任务的总时长
for(int i = 0;i < n;++i){
if(now + a[i].first <= a[i].second){ //若允许选择此任务
pq.push(a[i].first); //将任务时长压入堆中
now += a[i].first; //更新总时长
res++; //更新选择任务数量
}
else{
if(!pq.empty() && a[i].first < pq.top()){ //满足当前任务所需时长更短
int hd = pq.top();pq.pop();
pq.push(a[i].first);
now -= hd; //更新已选择任务以及总时长
now += a[i].first;
}
}
}
printf("%d\n",res);
return 0;
} 
京公网安备 11010502036488号