基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
有N个任务,每个任务有一个最晚结束时间以及一个对应的奖励。在结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。
Input
第1行:一个数N,表示任务的数量(2 <= N <= 50000) 第2 - N + 1行,每行2个数,中间用空格分隔,表示任务的最晚结束时间E[i]以及对应的奖励W[i]。(1 <= E[i] <= 10^9,1 <= W[i] <= 10^9)
Output
输出能够获得的最高奖励。
Input示例
7 4 20 2 60 4 70 3 40 1 30 4 50 6 10
Output示例
230
思路:优先队列/贪心+并查集
一:优先队列-由后向前:先将任务按照完成时间由大到小排序,由最晚完成时间开始安排任务,将所有可以安排的任务放入优先队列Q(价值大的优先),每次安排队列Q.top()即可,由于E[i]<=10^9,可能会超时,因此当队列Q中为空时,可将时间直接跳到下一任务上。
二:优先队列-由前向后:将任务按照完成时间由小到大排序,由最早完成时间开始安排任务,将任务放入优先队列Q(价值小的优先)中,若当前任务的完成时间大于队列中的任务个数,则将最小价值的出队即可。
三:贪心+并查集:将任务按照价值由大到小排序,先安排价值大的任务,按照贪心策略,应该将其安排在它最晚时间点上,对于已经安排的时间点,用并查集记录其前面最近的未安排的时间点,由于E[i]<=10^9太大,而n<=50000,因此对于E[i]>n的任务说明它安排在任意时间点上,因此可以将其修改为n。这样每次查询e[i]点所能够安排的最大时间点,若其为0说明没有时间点可以安排,否则修改其记录值。
Code 1:
//优先队列-由后到前
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
struct node{
int time;
int w;
bool operator<(const node &p)const{
return time>p.time;
}
};
const int MAX_N=100005;
int n;
node a[MAX_N];
int main()
{
ios::sync_with_stdio(false);
while(cin>>n){
LL ans=0;
priority_queue<LL> Q;
for(int i=0;i<n;++i)
cin>>a[i].time>>a[i].w;
sort(a,a+n);
int t=a[0].time,k=0;
while(t){
while(a[k].time>=t&&k<n){
Q.push(a[k++].w);
}
if(!Q.empty()){
ans+=Q.top(); Q.pop();
}else t=a[k].time+1; //队列为空则可以直接到下一任务点
t--;
}
cout<<ans<<endl;
}
return 0;
}
Code 2:
//优先队列-由前到后
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
struct node{
int time;
int w;
bool operator<(const node &p)const{
return time<p.time;
}
};
const int MAX_N=100005;
int n;
node a[MAX_N];
int main()
{
ios::sync_with_stdio(false);
while(cin>>n){
LL ans=0;
priority_queue<int,vector<int>,greater<int>> Q;
for(int i=0;i<n;++i)
cin>>a[i].time>>a[i].w;
sort(a,a+n);
for(int i=0;i<n;++i)
{
ans+=a[i].w; Q.push(a[i].w);
if(a[i].time<Q.size()){
ans-=Q.top(); Q.pop();
}
}
cout<<ans<<endl;
}
return 0;
}
Code 3:
//贪心-并查集
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
struct node{
int time;
int w;
bool operator<(const node &p)const{
return w>p.w;
}
};
const int MAX_N=50005;
int n;
int id[MAX_N];
node a[MAX_N];
int Find(int x);
int main()
{
ios::sync_with_stdio(false);
while(cin>>n){
for(int i=0;i<n;++i)
{
cin>>a[i].time>>a[i].w;
id[i]=i;
if(a[i].time>n) a[i].time=n;
}
id[n]=n;
sort(a,a+n);
for(int i=0;i<n;++i)
if(Find(id[a[i].time])) id[Find(id[a[i].time])]-=1;
else a[i].w=0;
LL ans=0;
for(int i=0;i<n;++i)
ans+=a[i].w;
cout<<ans<<endl;
}
return 0;
}
int Find(int x)
{
if(id[x]!=x) id[x]=Find(id[x]);
return id[x];
}