51nod 1163 最高的奖励
题目链接:http://class.51nod.com/Challenge/Problem.html#problemId=1163
一、题目描述
有N个任务,每个任务有一个最晚结束时间以及一个对应的奖励。
在结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。
有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。
输入描述
第1行:一个数N,表示任务的数量(2 <= N <= 50000) 第2 - N + 1行,每行2个数,中间用空格分隔,表示任务的最晚结束时间E[i]以及对应的奖励W[i]。(1 <= E[i] <= 10^9,1 <= W[i] <= 10^9)
输出描述
输出能够获得的最高奖励。
样例输入
7 4 20 2 60 4 70 3 40 1 30 4 50 6 10
样例输出
230
二、解题思路
这道题我们需要将每个活动的结束时间和在结束时间做完这个活动的奖励组合起来。
先准备完成所有的任务,直到出现冲突,我们再放弃某个任务。
在必须要放弃任务时,我们尽量选择奖励低的任务放弃。这样就能使我们获得的奖励最多。
所以我们先将任务按照结束时间排序,早结束的放在前面,然后逐个将任务加入到优先队列。
我们假设有一个任务的结束时间为e。
如果优先队列中的任务数量大于e的情况,则放弃奖励最低的任务。
三、代码描述
#include<queue> #include<vector> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; long long n, ans, before; priority_queue <int, vector <int>, greater <int> > q; struct node{ long long x;//最晚结束时间 long long val;//获得的奖励 }a[100010]; bool cmp(node a, node b){ return a.x < b.x;//按照时间来排序,结束时间越早排在越前面 } int main(){ cin >> n; for(int i = 0;i < n;i++){ cin >> a[i].x >> a[i].val; } sort(a, a+n, cmp); for(int i = 0;i < n;i++){ //如果a[i]最晚的结束时间比目前存的数量要晚 //说明是还能在时间可以的情况下再进行一个活动的 if(a[i].x > q.size()){ q.push(a[i].val);//把奖励存到优先队列里 ans += a[i].val;//ans还得加上奖励 }else{//如果时间不允许,判断要不要把以前的活动的给替换掉 before = q.top();//以前最少的奖励 if(a[i].val > before){//如果这次的奖励比以前的最小奖励值还多 q.pop();//把以前的最小值删除掉 q.push(a[i].val);//把这次的奖励存到优先队列里 ans = ans - before + a[i].val; //因为以前的最小值肯定在ans里面存过了 //所以如果再次把这次新的最小值存进去的话 //肯定是重复了一部分的 //因此要把两数之差存进去 } } } cout << ans << endl; return 0; }