游戲通關
【題目描述】
XY在玩一個包含N個任務的游戲。每個任務完成時限為Ti(你可以認為還沒開始做任務時的時間為0),獎勵為Wi。由於XY技術的嫻熟以及任務的簡單,對於每個任務,他都可以在一個單位時間內完成。
XY想要知道他能夠獲得的最多的獎勵。
【輸入】
第一行一個整數N,表示需要完成的任務數目。
接下來N行,每行兩個整數T、W,分別表示完成這個任務的最后期限和完成這個任務后獲得的獎勵。
【輸出】
輸出數據有且僅有一行,只包含一個整數,表示最多獲得的獎勵。
【輸入樣例】
2
1 5
1 4
【輸出樣例】
5
【樣例輸入2】
5
2 3
1 2
4 5
1 3
3 4
【樣例輸出2】
15
【樣例解釋2】
對於樣例2,XY可以選擇完成任務1、3、4和5,這樣他可以獲得獎勵15。
【數據規模及約定】
對於10%的數據,N≤100,Ti≤100,Wi≤2000。
對於30%的數據,N≤1000,Ti≤5000,Wi≤2000。
對於50%的數據,N≤10000,Ti≤20000,Wi≤2000。
對於100%的數據,N≤200000,Ti≤200000,Wi≤2000。
【思路】
貪心 + 大根堆的題目,感jio一本通就喜歡貪心 + 大根堆的題目瞎說的
比較好想的貪心題目
因為這個在每一個單位時間內都可以得到一個獎勵
所以只需要將每個單位時間內能夠得到的最高的獎勵累加起來就好了
不過一個單位時間內的最高獎勵不只有自己這個單位時間之前完成的那些任務
還有在這個單位時間之后完成的任務
可以這樣想,任務1在a時間之前完成
那么就可以在時間為a-1的時候去完成任務1
依次類推下去a - 2,a - 3……都是可以去完成任務1的
所以每一個單位時間x可以得到的最高獎勵是x+1到最晚的那個時間點的所有任務里面獎勵值最大的那個
這樣就可以想到倒着枚舉,放入大根隊中,加上隊首就好了
【易錯易漏】
容易在貪心求某個點a能夠得到的最高獎勵的時候,只求在這個點之前要求完成的任務,也就是只有那些要求在時間a之前完成的任務(不包括前面的也不包括后面的),這個時候糾錯掉了我就是在這里錯掉的。
【完整代碼】
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int Max = 200005;
struct node
{
int t,v;
}a[Max];
priority_queue<int>q;
bool cmp(const node x,const node y)
{
return x.t > y.t;
}
int n;
int main()
{
int ttt = 0;
scanf("%d",&n);
for(int i = 1;i <= n;++ i)
scanf("%d%d",&a[i].t,&a[i].v),ttt = max(a[i].t,ttt);
sort(a + 1,a + 1 + n,cmp);
int ans = 0;
int js = 0;
for(int i = ttt;i >= 1;i --)
{
while(a[++ js].t >= i)q.push(a[js].v);
js --;
if(!q.empty())
{
ans += q.top();
q.pop();
}
}
cout << ans << endl;
return 0;
}