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 ...
随机推荐
- Ubuntu11.04安装引导BURG
时间:11-05-10 BURG是一个漂亮的引导程序,可以代替ubuntu默认的引导. ubuntu11.04安装方法如下: sudo add-apt-repository ppa:n-muen ...
- HDU 3277 Marriage Match III(并查集+二分答案+最大流SAP)拆点,经典
Marriage Match III Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- Effective Java 第三版——44. 优先使用标准的函数式接口
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 判断一棵二叉树是否为AVL树
思路:AVL树是高度平衡的二叉搜索树,这里为了清晰说明,分别判断是否为搜索树,是否为平衡树. struct TreeNode { struct TreeNode *left; struct TreeN ...
- 解决python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX
从网上抓了一些字节流,想打印出来结果发生了一下错误: UnicodeEncodeError: 'gbk' codec can't encode character '\xbb' in position ...
- 编写自定义Yeoman生成器简述
1. 安装生成器Yeoman提供了generator-generator方便快速编写自己的生成器. 安装: npm install -g generator-generator运行: yo gener ...
- 使用Ajax异步上传图片的方法(html,javascript,php)
前两天项目中需要用到异步上传图片和显示上传进度的功能,于是找了很多外国的文章,翻山越岭地去遇上各种坑,这里写篇文章记录一下. HTML <form id="fileupload-for ...
- Spark学习笔记——数据读取和保存
spark所支持的文件格式 1.文本文件 在 Spark 中读写文本文件很容易. 当我们将一个文本文件读取为 RDD 时,输入的每一行 都会成为 RDD 的 一个元素. 也可以将多个完整的文本文件一次 ...
- How to get all Errors from ASP.Net MVC modelState?
foreach (ModelState modelState in ViewData.ModelState.Values) { foreach (ModelError error in modelSt ...
- [hadoop] hadoop native libraries 编译
安装hadoop启动之后总有警告:Unable to load native-hadoop library for your platform... using builtin-Javaclasses ...