POJ1456 Supermarket 题解

思维题。
关键在于如何想到用堆来维护贪心的策略。
首先肯定是卖出的利润越大的越好,但有可能当前这天选定了利润最大的很久才过期而利润第二大的第二天就过期,这时的策略就不优了。
所以我们必须动态改变策略,使整体最优。
先按过期时间排序,按顺序遍历,对于每一个商品,如果过期时间大于当前已决定要卖的商品的个数,那么这个东西就也要被卖出。
如果过期时间等于当前已决定要卖的商品的个数,那么这个商品是否要被卖出取决于利润是否大于已决定要卖的商品的最小利润,如果是那么决策显然会变得更优,替换掉最小的商品即可。
根据以上的分析,小根堆明显有利于我们维护这样的决策。这里的小根堆实际上是一个按时间轴顺序排好的“卖出清单”,始终保持了决策的最优性。
总结一下,本题的贪心关键在于这天没过期就先卖出去,等碰见利润比它大的就把它顶掉

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int n;
struct P{int p,d;}a[10005];
priority_queue<int,vector<int>,greater<int> > Q;
bool cmp(P x,P y) {return x.d==y.d?x.p<y.p:x.d<y.d;}
int main()
{
    while(~scanf("%d",&n))
    {
        int siz=0,ans=0;
        for(int i=1;i<=n;++i) scanf("%d%d",&a[i].p,&a[i].d);
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;++i)
        {
            if(a[i].d==siz)
            {
                if(a[i].p>Q.top()) {Q.pop(); Q.push(a[i].p);}
            }
            else if(a[i].d>siz) {Q.push(a[i].p);siz++;}
        }
        while(!Q.empty()) {ans+=Q.top(); Q.pop();}
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wzzyr24/p/12064607.html