题目链接:https://www.acwing.com/problem/content/147/
容易想到一个贪心策略:在最优解中,对于每个时间(天数) t,应该在保证不卖出过期商品的前提下,尽量卖出利润前t大的商品。因此,我们可以依次考虑每个商品,动态维护一个满足上述性质的方案。
详细地说,我们把商品按照过期时间排序,建立一个初始为空的小根堆 (节点权值为商品利润),然后扫描每个商品:
1.若当前商品的过期时间(天数) t等于当前堆中的商品个数,则说明在目前方案下,前t天已经安排了t个商品卖出。此时,若当前商品的利润大于堆顶权值(即已经安排的t个商品中的最低利润),则替换掉堆顶(用当前商品替换掉原方案中利润最低的商品)。
2.若当前商品的过期时间(天数)大于当前堆中的商品个数,直接把该商品插入堆。
3.若当前商品的过期时间(天数)小于当前堆中商品的个数,哦!!!不可能,因为在第一种情况中,若当前商品的过期时间(天数) t等于当前堆中的商品个数,我们就会替换掉商品。
最终,堆里的所有商品就是我们需要卖出的商品,它们的利润之和就是答案。该算法的时间复杂度为O(N logN)。
#include<iostream> #include<vector> #include<algorithm> #include<queue> using namespace std; struct node{ int val; int time; }nodes[10050]; bool operator <(const node &a, const node &b) { return a.time<b.time; } int main(){ int n; while (cin>>n) { for (int i = 1; i <= n; ++i) { cin>>nodes[i].val>>nodes[i].time; } sort(nodes+1,nodes+n+1); priority_queue<int,vector<int>, greater<int> > q; for (int i = 1 ; i <=n; ++i) { int currentDay=nodes[i].time; if (currentDay>q.size()) { q.push(nodes[i].val); }else { int vals=q.top(); if(vals<nodes[i].val){ q.pop(); q.push(nodes[i].val); } } } int ans=0; while (!q.empty()) { ans+=q.top(); q.pop(); } cout<<ans<<endl; } return 0; }