Supermarket
题目大意:
超市有n种商品,每个商品都有一个利润和保质期,超市每天只可以卖一种商品,求超市在保质期内卖出商品可获得的最大利益。
思路:
贪心+二叉堆优化
在最大的保质期时间内找出利润最大的商品卖掉,这个贪心思路是正确的,我们会发现我们的每一个选择都会被商品的保质期影响,即我们必须在商品的保质期内卖出商品,所以我们可以将保质期与可选择的次数相结合,得到以下方法:
将每种商品的保质期按从小到大顺序排序。
使用小根堆维护已经选择商品的价值,然后继续选择商品,这时会有这两种情况:
1.当前商品的保质期大于已经选择商品的次数,直接将此商品加入选择之中;
2.当前商品的保质期等于已经选择商品的次数,将这个商品的价值与小根堆的堆顶作比较,如果大于即替换,否则不变。
因为每次都选择最优的选项,保证了算法的正确性。
代码:
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pb push_back #define mp make_pair #define lowbit(x) x&(-x) typedef long long ll; typedef pair<int,int> pii; typedef pair<ll, ll> pll; const int N = 1e4+5; const ll mod = 1e9+7; const int INF = 0x3f3f3f3f; const double eps =1e-9; const double PI=acos(-1.0); const int dir[8][2]={-1,0,1,0,0,-1,0,1,1,1,1,-1,-1,1,-1,-1}; ll qpow(ll x,ll y){ ll ans=1,t=x; while(y>0){ if(y&1)ans*=t,ans%=mod; t*=t,t%=mod; y>>=1; } return ans%mod; } int p[N],t[N],c[N]; bool cmp(int x,int y){return t[x]<t[y];} void solve(){ int n; while(cin>>n){ for(int i=1;i<=n;i++)cin>>p[i]>>t[i]; for(int i=1;i<=n;i++)c[i]=i; sort(c+1,c+n,cmp); priority_queue<int,vector<int>,greater<int>>q; int sum=0; for(int i=1;i<=n;i++){ int x=c[i]; if(t[x]>q.size())q.push(p[x]),sum+=p[x]; else { if(q.top()<p[x])sum+=p[x]-q.top(),q.pop(),q.push(p[x]); } } cout<<sum<<endl; } } int main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); //int t;cin>>t; //while(t--)solve(),cout<<'\n'; solve(); return 0; }