《算法竞赛进阶指南》超市

超市

超市里有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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值