超市
超市里有N件商品,每件商品都有利润pi和过期时间di,每天只能卖一件商品,过期商品不能再卖。
求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。
输入格式
输入包含多组测试用例。
每组测试用例,以输入整数N开始,接下来输入N对pi和di,分别代表第i件商品的利润和过期时间。
在输入中,数据之间可以自由穿插任意个空格或空行,输入至文件结尾时终止输入,保证数据正确。
输出格式
对于每组产品,输出一个该组的最大收益值。
每个结果占一行。
数据范围
0≤N≤10000,
1≤pi,di≤10000
最多有14组测试样例
输入样例:
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
本题的思想是动态规划,应用的数据结构是小根堆,这里我们用优先队列建立小根堆。
我们朴素的思想应该是有效期短的先出售,其次在考虑商品收益的问题,这样我们将每一个商品建立两个属性包括有效期和收益,优先将有效期排序,然后在对收益进行排序。然后我们维护一个“动态池”,我们在对排序之后的商品进行整体的遍历,每次遍历相当于天数加一,每次都先插入当前商品,只要当前“动态池”大小(即天数)大于当前商品的有效期,就说明当前“动态池”里需要去除一个商品,去除的我们要求是收益最小的这样才能使整体收益最大,这样每次寻找最小值的数据结构就是小根堆,“动态池”就是我们建立的小根堆。
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int n;
while(cin>>n)
{
vector<pair<int ,int > > products(n);
//我们建立vector,每一个值有两个属性即有效期时长和价值
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++)
{//我们把n个数据遍历一遍,每次动态维护出售商品的“池”
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;
}
return 0;
}