题目链接: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 - [贪心+小顶堆]的更多相关文章

  1. CodeForces - 867E Buy Low Sell High (贪心 +小顶堆)

    https://vjudge.net/problem/CodeForces-867E 题意 一个物品在n天内有n种价格,每天仅能进行买入或卖出或不作为一种操作,可以同时拥有多种物品,问交易后的最大利益 ...

  2. nyoj 208 + poj 1456 Supermarket (贪心)

    Supermarket 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 A supermarket has a set Prod of products on sal ...

  3. POJ 1456 Supermarket(贪心+并查集优化)

    一开始思路弄错了,刚开始想的时候误把所有截止时间为2的不一定一定要在2的时候买,而是可以在1的时候买. 举个例子: 50 2  10 1   20 2   10 1    50+20 50 2  40 ...

  4. POJ 2442 - Sequence - [小顶堆][优先队列]

    题目链接:http://poj.org/problem?id=2442 Time Limit: 6000MS Memory Limit: 65536K Description Given m sequ ...

  5. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  6. heap c++ 操作 大顶堆、小顶堆

    在C++中,虽然堆不像 vector, set 之类的有已经实现的数据结构,但是在 algorithm.h 中实现了一些相关的模板函数.下面是一些示例应用 http://www.cplusplus.c ...

  7. python 基于小顶堆实现随机抽样

    起因:之前用蓄水池抽样,算法精简,但直观性很差. 所以这次采用了简单的,为没一个行,赋值一个随机值,然后取 最大的K个作为,随机样本. 基本思路:为每一个行(record,记录,实体) 赋一个rand ...

  8. Python使用heapq实现小顶堆(TopK大)、大顶堆(BtmK小)

    Python使用heapq实现小顶堆(TopK大).大顶堆(BtmK小) | 四号程序员 Python使用heapq实现小顶堆(TopK大).大顶堆(BtmK小) 4 Replies 需1求:给出N长 ...

  9. BZOJ 1150 - 数据备份Backup - [小顶堆][CTSC2007]

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1150 Time Limit: 10 Sec Memory Limit: 162 M De ...

随机推荐

  1. System Monitor for Mac(系统监控工具)破解版安装

    1.软件简介    System Monitor 是 macOS 系统上的一款非常实用的 Mac 系统工具,System Monitor for mac 是一款六合一应用,您可以同时获得 CPU.RA ...

  2. 我的Nginx配置文件

    #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...

  3. Golang——垃圾回收GC

    Go 垃圾回收原理 Golang源码探索(三) GC的实现原理 引用计数:对每个对象维护一个引用计数,当引用该对象的对象被销毁时,引用计数减1,当引用计数器为0是回收该对象. 优点:对象可以很快的被回 ...

  4. 【GMT43智能液晶模块】例程一:ARM驱动LED

    实验原理: 通过STM32的一个GPIO驱动一个红色LED,GPIO为推挽输出模式,采用灌电流 方式与LED连接,基于STemWin人机界面通过按钮控制GPIO高.低电平输出,从而 控制LED亮灭. ...

  5. iTunes空间不足无法备份iphone的问题

    因为换手机,需要把旧iphone备份出来,在新iphone上恢复.使用mac进行备份时总是提示iTunes无法备份,所用电脑空间不够,即使有个用空间的移动硬盘也无法备份.网上的方法都是说修改iTune ...

  6. Spark学习笔记——手写数字识别

    import org.apache.spark.ml.classification.RandomForestClassifier import org.apache.spark.ml.regressi ...

  7. 如何使用ABBYY FineReader 12将JPEG文件转换成Word文档

    日常工作中处理JPEG格式的图像文件时,有时需要转换成Word文档进行编辑,市场上应用而生了很多转换工具,相信不少人听说过OCR(光学字符识别)软件,可以用来转换图像文件,而在OCR软件中, ABBY ...

  8. python -u 启动python文件的作用,PYTHONUNBUFFERED环境变量的作用

    python -u 启动python文件的作用是不缓存,直接把输出重定向到文件,比如nohup启动什么的,如果不使用-u启动,那么程序中的print和日志什么的,可能不会非常及时的重定向到out文件, ...

  9. [Model] AlexNet

    CaffeNet - a variant of AlexNet Ref: Classification: Instant Recognition with Caffe This is caffeNet ...

  10. [Node.js] 05 - Modules and Function

    一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码.JSON 或者编译过的C/C++ 扩展. 模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的. No ...