题目:
原题如下:
有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
思路:
如果只用普通的贪心是可以的,因为这个题他有个隐藏的条件,那就是可以提前用。
如果题目是说这个题只能在这一刻做,那么就直接贪心,但是这个可以提前。
也就是说对于t时刻时,我们一共最多能完成t-1个题,但是这t-1个题,只要是在规定时间内即可。
我们遍历所有的题目,对于当前题目,得到他是最晚运行时间z。
如果队列(我们做了的题目)数量小于z,也就是说我们这个z这个题目可以做,直接做即可。
如果数量大于等于z了,我们这道题做还是不做,要看看里面还有没有更小的,把获得价值最小的题目取出来,把这个放进去即可。
对于这种最晚运行,这种要求的题目,用到了优先队列。
原文:https://blog.csdn.net/little_boy_z/article/details/78501710?utm_source=copy
C++队列Queue类成员函数有:
back() 返回最后一个元素
empty() 如果队列空则返回真
front() 返回第一个元素
pop() 删除第一个元素
size() 返回队列中元素的个数
AC代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int time;
int val;
}a[50010];
bool cmp(node t1,node t2)
{
if(t1.time==t2.time)
return t1.val>t2.val;
else return t1.time<t2.time;
}
int main()
{
int i,j,n;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&a[i].time,&a[i].val);
}
sort(a,a+n,cmp);
long long int ans=0; //ans最后加起来有可能超过int的
priority_queue<int,vector<int>,greater<int> > pq;
for(int i=0;i<n;i++)
{
int k=a[i].val;
if(a[i].time>pq.size())//要插入的截止时间大于已加入任务用的总时间
{
ans+=k;
pq.push(k);
}
else
{
ans+=k;
pq.push(k);
int t=pq.top(); //替换掉栈顶那个价值最小的
pq.pop();
ans-=t;
}
}
cout<<ans<<endl;
return 0;
}