算法竞赛进阶指南-59.超市
题目链接
超市里有 件商品,每件商品都有利润 和过期时间 ,每天只能卖一件商品,过期商品不能再卖。
求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。
输入格式
输入包含多组测试用例。
每组测试用例,以输入整数 开始,接下来输入 对 和 ,分别代表第 件商品的利润和过期时间。
在输入中,数据之间可以自由穿插任意个空格或空行,输入至文件结尾时终止输入,保证数据正确。
输出格式
对于每组产品,输出一个该组的最大收益值。
每个结果占一行。
数据范围
,
最多有 组测试样例
输入样例:
4 50 2 10 1 20 2 30 1
7 20 1 2 1 10 3 100 2 8 2
5 20 50 10
输出样例:
80
185
Method : 贪心 + 优先队列
贪心策略:对于每个时间t,我们希望对于当前所有未过期的商品,在t天内尽可能选取利润前t大的商品
具体做法就是,首先按照过期时间来排序,然后按该次序从前往后遍历商品,并以商品价值建立一个小根堆:
把当前商品插入到堆中,如果当前商品的过期时间>堆中的商品数,因为之前所有的商品的过期时间都<=该商品的过期时间,所以如果以当前堆中的商品数为售卖天数t,必然不能把这些商品都卖光,因此需要弹出价值最小的商品(堆顶)。
这道题虽然思维难度不高,但是让我懂得了结构体的优先队列该怎么写最优美(重载operator >
)。
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e4 + 7;
struct Good {
int value;
int time;
bool operator >(const Good& rhs) const{
return value > rhs.value;
}
};
Good g[N];
int main() {
int n;
while (cin >> n) {
for (int i = 0; i < n; i ++) {
scanf("%d %d", &g[i].value, &g[i].time);
}
sort(g, g + n, [](const Good& a, const Good& b) {
if (a.time == b.time) return a.value < b.value;
return a.time < b.time;
});
priority_queue<Good, vector<Good>, greater<Good>> pq;
for (int i = 0; i < n; i ++) {
pq.push(g[i]);
if (pq.size() > g[i].time) pq.pop();
}
int res = 0;
while (!pq.empty()) {
res += pq.top().value; pq.pop();
}
printf("%d\n", res);
}
return 0;
}
复杂度分析
时间复杂度:,sort是的,n次循环*pq的push() or pop也是。
空间复杂度:。
本博客所有文章均采用 CC BY-NC-SA 4.0 协议 ,禁止商用,转载请注明出处!