AcWing 超市

AcWing 超市

Description

  • 超市里有N件商品,每个商品都有利润pi和过期时间di,每天只能卖一件商品,过期商品(即当天di<=0)不能再卖。

    求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。

Input

  • 输入包含多组测试用例。

    每组测试用例,以输入整数N开始,接下里输入N对pi和,分别代表第i件商品的利润和过期时间。

    在输入中,数据之间可以自由穿插任意个空格或空行,输入至文件结尾时终止输入,保证数据正确。

Output

  • 对于每组产品,输出一个该组的最大收益值。

    每个结果占一行。

Sample Input

4  50 2  10 1   20 2   30 1

7  20 1   2 1   10 3  100 2   8 2
   5 20  50 10

Sample Output

80
185

Data Size

  • 0≤N≤10000,
    1≤pi,di≤10000

题解:

  • 贪心 + 二叉堆。
  • 容易想到,在不卖出过期商品的前提下,尽量卖利润大的物品。所以先按物品过期时间排序,然后可以考虑用一个容器逐渐将每一个商品丢进去,同时动态维护容器使其是合法且最优的。
  • 具体就是用小根堆维护,堆里装物品权值。排序后扫描每个商品:
    1. 若当前商品过期时间 == 堆的size,那么看看能否将堆顶替换掉,能就换走。
    2. 若当前商品过期时间 > 堆的size,直接插入。
  • 最终堆中所有元素之和即为所求。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#define N 10005
#define int long long
using namespace std;

struct A {int v, t;} a[N];
int n, ans;
priority_queue<int, vector<int>, greater<int> > que;

int read()
{
    int x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
    return x;
}

bool cmp(A x, A y) {return x.t < y.t;}

signed main()
{
    while(scanf("%lld", &n) == 1)
    {
        ans = 0;
        for(int i = 1; i <= n; i++)
            a[i].v = read(), a[i].t = read();
        sort(a + 1, a + 1 + n, cmp);
        for(int i = 1; i <= n; i++)
        {
            if(a[i].t > (int)que.size()) que.push(a[i].v);
            else if(a[i].v > que.top()) que.pop(), que.push(a[i].v);
        }
        while(que.size()) ans += que.top(), que.pop();
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BigYellowDog/p/11349491.html