POJ 1456 - Supermarket - [贪心+小顶堆]
题目链接:http://poj.org/problem?id=1456
Time Limit: 2000MS Memory Limit: 65536K
Description
A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an integral number of time units starting from the moment the sale begins. Each product takes precisely one unit of time for being sold. A selling schedule is an ordered subset of products Sell ≤ Prod such that the selling of each product x∈Sell, according to the ordering of Sell, completes before the deadline dx or just when dx expires. The profit of the selling schedule is Profit(Sell)=Σx∈Sellpx. An optimal selling schedule is a schedule with a maximum profit.
For example, consider the products Prod={a,b,c,d} with (pa,da)=(50,2), (pb,db)=(10,1), (pc,dc)=(20,2), and (pd,dd)=(30,1). The possible selling schedules are listed in table 1. For instance, the schedule Sell={d,a} shows that the selling of product d starts at time 0 and ends at time 1, while the selling of product a starts at time 1 and ends at time 2. Each of these products is sold by its deadline. Sell is the optimal schedule and its profit is 80.
Write a program that reads sets of products from an input text file and computes the profit of an optimal selling schedule for each set of products.
Input
A set of products starts with an integer 0 <= n <= 10000, which is the number of products in the set, and continues with n pairs pi di of integers, 1 <= pi <= 10000 and 1 <= di <= 10000, that designate the profit and the selling deadline of the i-th product. White spaces can occur freely in input. Input data terminate with an end of file and are guaranteed correct.
Output
For each set of products, the program prints on the standard output the profit of an optimal selling schedule for the set. Each result is printed from the beginning of a separate line.
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
Hint
The sample input contains two product sets. The first set encodes the products from table 1. The second set is for 7 products. The profit of an optimal schedule for these products is 185.
题意:
给定 $n$ 个商品,每个商品有利润 $p_i$ 和过期时间 $d_i$,每天只能卖出一个商品,过期商品就不能在卖了,求如何安排每天卖的商品,使得利润最大。
题解:
很遥远的以前我们曾用贪心做过这道题目,大致思路是:优先考虑利润最大的商品,但是对每件商品尽可能安排越晚卖出越好,以方便给之后的商品留空间。时间复杂度 $O(n \log n + n \times max(d_i))$,
这次我们换一种更加直接贪心思路:假设当前是第 $k$ 天,那么当目前为止一共 $k$ 天时间,我要做的就是在保证不卖过期商品的前提下,尽可能的卖出利润前 $k$ 大的商品。
因此,我们可以把商品按照过期时间升序排序,并且建立一个初始为空的小顶堆(键值为商品的利润)来维护一个满足上述性质的方案:
1、若当前商品的过期时间 $d_i$ 大于堆的 $size$,则直接入堆,代表安排卖出当前商品。
2、若当前商品的过期时间 $d_i$ 等于堆的 $size$,则说明前 $d_i$ 天已经安排卖出了 $size$ 个商品,只有当我的利润大于堆中利润最小的,才考虑用当前商品替换掉堆中利润最小的商品。
3、可以证明,不存在当前商品的过期时间 $d_i$ 小于堆 $size$ 的情况,因为最初堆 $size=0$,而 $d_i$ 最小为 $1$,因此第一个商品必然是情况1;而后,由于堆中节点是一个一个增加,而商品的遍历是过期时间单调不减的,因此必然存在第 $k$ 个商品使得 $d_k = size$(除非 $size$ 始终小于每个商品的过期时间),即产生情况2,那么根据情况2所描述的操作可知堆中元素不会再增加,而第 $k+1$ 个商品的过期时间必然不小于第 $k$ 个商品,因此在第 $k$ 个商品时必然有 $d_{k+1} \ge size$,以此类推易知始终达不到 $d_i < size$ 的情况。
最后,遍历完所有商品,堆中即存储了所有要安排卖出的商品,对这些商品的利润求和即得答案。时间复杂度 $O(n \log n)$。
AC代码:
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
const int maxn=+; struct Heap
{
int sz;
int heap[maxn];
void up(int now)
{
while(now>)
{
int par=now>>;
if(heap[now]<heap[par]) //子节点小于父节点,不满足小顶堆性质
{
swap(heap[par],heap[now]);
now=par;
}
else break;
}
}
void push(int x) //插入权值为x的节点
{
heap[++sz]=x;
up(sz);
}
inline int top(){return heap[];}
void down(int now)
{
while((now<<)<=sz)
{
int nxt=now<<;
if(nxt+<=sz && heap[nxt+]<heap[nxt]) nxt++; //取左右子节点中较小的
if(heap[now]>heap[nxt]) //子节点小于父节点,不满足小顶堆性质
{
swap(heap[now],heap[nxt]);
now=nxt;
}
else break;
}
}
void pop() //移除堆顶
{
heap[]=heap[sz--];
down();
}
void del(int p) //删除存储在数组下标为p位置的节点
{
heap[p]=heap[sz--];
up(p), down(p);
}
inline void clr(){sz=;}
}; int n;
vector<pii> P; //first为过期时间,second为利润
Heap h; int main()
{
while(cin>>n)
{
P.clear();
for(int i=,p,d;i<=n;i++)
{
scanf("%d%d",&p,&d);
P.push_back(make_pair(d,p));
}
sort(P.begin(),P.end()); h.clr();
for(int i=;i<P.size();i++)
{
if(P[i].first>h.sz) h.push(P[i].second);
else if(P[i].first==h.sz && P[i].second>h.top())
{
h.pop();
h.push(P[i].second);
}
} int sum=;
while(h.sz)
{
sum+=h.top();
h.pop();
}
printf("%d\n",sum);
}
}
POJ 1456 - Supermarket - [贪心+小顶堆]的更多相关文章
- CodeForces - 867E Buy Low Sell High (贪心 +小顶堆)
https://vjudge.net/problem/CodeForces-867E 题意 一个物品在n天内有n种价格,每天仅能进行买入或卖出或不作为一种操作,可以同时拥有多种物品,问交易后的最大利益 ...
- nyoj 208 + poj 1456 Supermarket (贪心)
Supermarket 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 A supermarket has a set Prod of products on sal ...
- POJ 1456 Supermarket(贪心+并查集优化)
一开始思路弄错了,刚开始想的时候误把所有截止时间为2的不一定一定要在2的时候买,而是可以在1的时候买. 举个例子: 50 2 10 1 20 2 10 1 50+20 50 2 40 ...
- POJ 2442 - Sequence - [小顶堆][优先队列]
题目链接:http://poj.org/problem?id=2442 Time Limit: 6000MS Memory Limit: 65536K Description Given m sequ ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- heap c++ 操作 大顶堆、小顶堆
在C++中,虽然堆不像 vector, set 之类的有已经实现的数据结构,但是在 algorithm.h 中实现了一些相关的模板函数.下面是一些示例应用 http://www.cplusplus.c ...
- python 基于小顶堆实现随机抽样
起因:之前用蓄水池抽样,算法精简,但直观性很差. 所以这次采用了简单的,为没一个行,赋值一个随机值,然后取 最大的K个作为,随机样本. 基本思路:为每一个行(record,记录,实体) 赋一个rand ...
- Python使用heapq实现小顶堆(TopK大)、大顶堆(BtmK小)
Python使用heapq实现小顶堆(TopK大).大顶堆(BtmK小) | 四号程序员 Python使用heapq实现小顶堆(TopK大).大顶堆(BtmK小) 4 Replies 需1求:给出N长 ...
- BZOJ 1150 - 数据备份Backup - [小顶堆][CTSC2007]
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1150 Time Limit: 10 Sec Memory Limit: 162 M De ...
随机推荐
- Emacs 设置C++代码风格
;; C++代码风格设置 (defconst cobbcpp '("linux" ; this is inheritance from the linux style (c-bas ...
- Springmvc 整合 jetbrick 实例
应用环境: <jetbrick.version>1.2.8</jetbrick.version> <antlr4-runtime.version>4.2.2< ...
- 服务端怎样暴露IBinder接口对象
服务端怎样暴露IBinder接口对象: package com.example.mydownload; import android.app.Service; import android.conte ...
- Hexo NexT 博客后台管理指南
上篇文章讲到,将Hexo NexT 博客成功上传到GitHub 并绑定到我们自定义的域名下了. 但是却还是有个问题,那就是Hexo NexT 博客如何进行后台管理呢? 如果总是通过手动创建文件的方式, ...
- ios开发:一个音乐播放器的设计与实现
github地址:https://github.com/wzpziyi1/MusicPlauer 这个Demo,关于歌曲播放的主要功能都实现了的.下一曲.上一曲,暂停,根据歌曲的播放进度动态滚动歌词, ...
- python调用nmap探测局域网设备
平台:linux 描述:利用os.popen()函数调用系统命令nmap进行扫描,并用grep命令对扫描结果关键内容进行提取 代码 #!/usr/bin/env pthon #--*--coding= ...
- Nginx的upstream目前支持5种分配方式
本文转自:http://mp.weixin.qq.com/s?__biz=MzI4OTU3ODk3NQ==&mid=2247484058&idx=1&sn=f4da816bfa ...
- 安卓程序代写 网上程序代写[原]vim编辑器配置及常用命令
最近工作不安分, 没有了刚入行时候的锐气, 不知道什么时候开始懈怠起来, 周末在电脑旁边看新闻, 搞笑图片, 追美剧, 一坐就是一天, 很是空虚. 我需要摆脱这种状态, 正好想学习一下安卓底层, An ...
- HttpWebRequest - Asynchronous Programming Model/Task.Factory.FromAsyc
Posted by Shiv Kumar on 23rd February, 2011 The Asynchronous Programming Model (or APM) has been aro ...
- (转)java 中unsigned类型的转换
转自:http://blog.sina.com.cn/s/blog_77bf45a90101dld9.html 在Java中,不存在Unsigned无符号数据类型,但可以轻而易举的完成Unsigned ...