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
题解:
- 贪心 + 二叉堆。
- 容易想到,在不卖出过期商品的前提下,尽量卖利润大的物品。所以先按物品过期时间排序,然后可以考虑用一个容器逐渐将每一个商品丢进去,同时动态维护容器使其是合法且最优的。
- 具体就是用小根堆维护,堆里装物品权值。排序后扫描每个商品:
- 若当前商品过期时间 == 堆的size,那么看看能否将堆顶替换掉,能就换走。
- 若当前商品过期时间 > 堆的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;
}