思路:贪心策略+小顶堆数据结构
思路来源于算法进阶指南,我们的目的是在t的时间内获得更多的利润,该问题可以分解成许多子问题,即每天都卖出商品且保证商品的获利最大。
首先将所有商品按照过期时间从小到大排序;初始化一个空的小顶堆。然后遍历所有商品
1 : 如果当前商品的过期时间大于堆内商品总数,就将该商品直接插入堆内,然后进行调整,(表示着该商品可能在过期时间之前卖出)。
2 : 如果当前商品的过期时间等于堆内商品总数,就将该商品与小顶堆堆顶的节点利润进行比较,如果大于堆顶利润则替换,并向下调整即可。(这表示这在过期时间 t 内有 t 个商品可以卖出,为了尽可能获利, 就将与当前商品利润差最大的替换,即替换小顶堆堆顶替换)。
时空分析:
时间复杂度为 O(NlogN),N为每次商品数。
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <queue>
#include <stack>
using namespace std;
const int maxn=1e4+10;
int n,pr,da,cur_size; //n为每次输入的商品数,pr,da暂存每次输入商品利润和过期时间。
struct node{ //cur_size 保存当前堆内商品总数。
int pi,di;
}x;
vector<node> q,heap;
bool cmp(node a,node b){ //按照过期时间从小到大排序
return a.di<b.di;
}
void up(int p){ //向上调整
while(p>1){
if(heap[p].pi<heap[p/2].pi){
swap(heap[p],heap[p/2]);
p/=2;
}
else break;
}
}
void down(int p){ //向下调整
int s=p*2;
while(s<=cur_size){
if(s+1<=cur_size && heap[s].pi > heap[s+1].pi ) s++;
if(heap[p].pi > heap[s].pi){
swap(heap[p],heap[s]);
p=s;s*=2;
}
else break;
}
}
int main(){
while(scanf("%d",&n)!=EOF){
x.di=0,x.pi=0;
heap.clear();
q.clear();
heap.push_back(x); //堆下标从1开始,需要给0占位
cur_size=0;
for(int i=0;i<n;i++){
scanf("%d%d",&pr,&da);
x.pi=pr,x.di=da;
q.push_back(x);
}
sort(q.begin(),q.end(),cmp);
for(int i=0;i<n;i++){
if(q[i].di>cur_size){//插入调整
heap.push_back(q[i]);
cur_size++;
up(cur_size);
}
else if(q[i].di==cur_size && heap[1].pi<q[i].pi){ //替换调整
heap[1].pi=q[i].pi;
heap[1].di=q[i].di;
down(1);
}
}
int res=0;
for(int i=1;i<=cur_size;i++){ //最终堆内所有节点利润为总利润
res+=heap[i].pi;
}
cout<<res<<endl;
}
system("pause");
return 0;
}