题目链接
题目的大意就是每天可以卖一种商品,但每个商品都有自己的保质期,求最大的收益。转换一下,就是每天都尽量选择最大的商品卖,这里有两种解决方法,一种是贪心,一种是是二叉堆。
很容易想到这题的贪心解法,先对商品按价格进行排序,然后再选择在第几天卖掉它,因为我们要尽可能卖掉更多的商品,因此要选择尽量靠后的时间卖掉它。
下面看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int vis[N];
int n;
struct node{
int vi;
int day;
}goods[N];
bool cmp(node x, node y){
if(x.vi == y.vi) return x.day < y.day;
else return x.vi > y.vi;
}
int main(){
while(scanf("%d", &n) != EOF){
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++) cin >> goods[i].vi >> goods[i].day;
sort(goods+1, goods+n+1, cmp);
int sum = 0;
for(int i = 1; i <= n; i++){
int f = 0;
for(int j = goods[i].day; j >= 1; j--){
if(!vis[j]){
vis[j] = 1;
f = 1;
break;
}
}
if (f == 1) sum += goods[i].vi;
}
cout << sum << endl;
}
}
下面重点介绍利用二叉堆的写法。
简介:
二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最大堆和最小堆。最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
在stl标准库中就有二叉堆可以直接调用,就是priority_queue,这个容器默认是递减的大根堆,因此要让序列递增我们只要进行重载一下,利用greater就行了。知道这个之后接下来要怎么用呢?我们可以把当前容器内的当做我们已经选择要卖掉的,然后对每一个放进来的商品进行判断,当然先把商品按保质期从小到大排序,如果当前商品的保质期还小于等于容器的体积,那么可以直接放入,如果当前的商品的保质期大于容器的体积,那么我们就将容器中最小的出队,这样就可以维护堆中的和最大。
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef pair<int, int> PII;
int n;
int main(){
while(cin >> n) {
vector<PII> products(n);
for (int i = 0; i < n; i ++) cin >> products[i].second >> products[i].first;
sort(products.begin(), products.end());
priority_queue<int, vector<int>, greater<int>> heap;
for (int i = 0; i < n; i ++) {
heap.push(products[i].second);
if (heap.size() > products[i].first) heap.pop();
}
int res = 0;
while (heap.size()) res += heap.top(), heap.pop();
cout << res << endl;
}
}