AcWing:145. 超市(贪心 + 小根堆 or 贪心 + 并查集)
超市里有N件商品,每个商品都有利润pipi和过期时间didi,每天只能卖一件商品,过期商品(即当天di<=0di<=0)不能再卖。
求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。
输入格式
输入包含多组测试用例。
每组测试用例,以输入整数N开始,接下里输入N对pipi和didi,分别代表第i件商品的利润和过期时间。
在输入中,数据之间可以自由穿插任意个空格或空行,输入至文件结尾时终止输入,保证数据正确。
输出格式
对于每组产品,输出一个该组的最大收益值。
每个结果占一行。
数据范围
0≤N≤100000≤N≤10000,
1≤pi,di≤100001≤pi,di≤10000
输入样例:
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 <cstdio>
#include <queue>
#include <functional>
#include <algorithm> using namespace std; const int maxn = 1e5+; struct node {
int pi, di;
}arr[maxn]; priority_queue<int, vector<int>, greater<int> > p; //建立从小到大的优先队列(小根堆) bool cmp(node a, node b) {
return a.di < b.di;
} int main() {
int n;
while(~scanf("%d", &n)) {
for(int i = ; i <= n; i++) {
scanf("%d %d", &arr[i].pi, &arr[i].di);
}
sort(arr + , arr + n + , cmp);
for(int i = ; i <= n; i++) {
if(arr[i].di > p.size()) { //如果商品的过期天数大于当前天数,就直接进入队列
p.push(arr[i].pi);
} else if(arr[i].di == p.size() && arr[i].pi > p.top()) { //当商品的过去天数等于当前天数的时候,就比较一下当前商品是否比队列中最小的商品大,如果是就进入队列
p.pop();
p.push(arr[i].pi);
}
}
int ans = ;
while(!p.empty()) {
ans += p.top();
p.pop();
}
printf("%d\n", ans);
}
return ;
}
二叉堆实现小根堆:
#include <iostream>
#include <cstdio>
#include <algorithm> using namespace std; const int maxn = 1e5+; struct node {
int pi, di;
}arr[maxn];
int heap[maxn];
int tot; bool cmp(node a, node b) {
return a.di < b.di;
} void up(int n) {
while(n > ) {
if(heap[n] < heap[n / ]) {
swap(heap[n], heap[n / ]);
}
n /= ;
}
} void insert(int val) {
heap[++tot] = val;
up(tot);
} void down(int n) {
int s = n * ;
while(s <= tot) {
if(s < tot && heap[s] > heap[s + ]) { //找出左右子树中较小的那个
s++;
}
if(heap[s] < heap[n]) {
swap(heap[s], heap[n]);
}
n = s;
s = * n;
} } void update(int val) {
heap[] = val;
down();
} int main() {
int n;
while(~scanf("%d", &n)) {
for(int i = ; i <= n; i++) {
scanf("%d %d", &arr[i].pi, &arr[i].di);
}
sort(arr + , arr + n + , cmp);
tot = ;
for(int i = ; i <= n; i++) {
if(arr[i].di > tot) {
insert(arr[i].pi);
} else if(arr[i].di == tot && arr[i].pi >heap[]) {
update(arr[i].pi);
}
}
int ans = ;
for(int i = ; i <= tot; i++) {
ans += heap[i];
}
printf("%d\n", ans);
}
return ;
}
并查集:
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm> using namespace std; const int maxn = 1e4+; struct node {
int weight, date;
friend bool operator < (node a, node b) {
if(a.weight == b.weight) {
return a.date > b.date;
}
return a.weight > b.weight;
}
}; vector<node> v;
int f[maxn]; int find(int x) {
if(f[x] != x) {
return f[x] = find(f[x]);
}
return f[x];
} int main() {
int n;
while(~scanf("%d", &n)) {
v.clear();
int maxe = ;
for(int i = ; i < n; i++) {
int x, y;
scanf("%d %d", &x, &y);
v.push_back((node){x, y});
maxe = max(maxe, y);
}
for(int i = ; i <= maxe; i++) {
f[i] = i;
}
sort(v.begin(), v.end()); //按权值从大到小排序
int size = v.size();
int ans = ;
for(int i = ; i < size; i++) {
int w = v[i].weight;
int d = v[i].date;
int pos = find(d); //找到当前日期的最佳位置
if(pos > ) { //如果该位置没有出界,那么就可以使用
ans += w;
f[pos] = pos - ;
}
}
printf("%d\n", ans);
}
return ;
}
AcWing:145. 超市(贪心 + 小根堆 or 贪心 + 并查集)的更多相关文章
- AcWing:111. 畜栏预定(贪心 + 小根堆)
有N头牛在畜栏中吃草. 每个畜栏在同一时间段只能提供给一头牛吃草,所以可能会需要多个畜栏. 给定N头牛和每头牛开始吃草的时间A以及结束吃草的时间B,每头牛在[A,B]这一时间段内都会一直吃草. 当两头 ...
- UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】
题目分析: 好像跑得很快,似乎我是第一个启发式合并的. 把玩具看成区间.首先很显然如果有两个玩具的进出时间有$l1<l2<r1<r2$的关系,那么这两个玩具一定在不同的栈中间. 现在 ...
- AcWing:146. 序列(小根堆 + 数学归纳 + 贪心)
给定m个序列,每个包含n个非负整数. 现在我们可以从每个序列中选择一个数字以形成具有m个整数的序列. 很明显,我们一共可以得到nmnm个这种序列, 然后我们可以计算每个序列中的数字之和,并得到nmnm ...
- [CSP-S模拟测试]:梦境(贪心+小根堆)
题目描述 智者奥尔曼曾说过:有缘的人即使相隔海角天涯,也会在梦境中相遇. $IcePrince\text{_}1968$和$IcePrincess\text{_}1968$便是如此.有一天$IcePr ...
- 【BZOJ4388】JOI2012 invitation 堆+线段树+并查集(模拟Prim)
[BZOJ4388]JOI2012 invitation Description 澳洲猴举办了一场宴会,他想要邀请A个男生和B个女生参加,这A个男生从1到A编号,女生也从1到B编号.现在澳洲猴知道n组 ...
- AcWing:238. 银河英雄传说(带权并查集)
有一个划分为N列的星际战场,各列依次编号为1,2,…,N. 有N艘战舰,也依次编号为1,2,…,N,其中第i号战舰处于第i列. 有T条指令,每条指令格式为以下两种之一: 1.M i j,表示让第i号战 ...
- POJ 1456 Supermarket(贪心+并查集)
题目链接:http://poj.org/problem?id=1456 题目大意:有n件商品,每件商品都有它的价值和截止售卖日期(超过这个日期就不能再卖了).卖一件商品消耗一个单位时间,售卖顺序是可以 ...
- bzoj 1455 可并堆+并查集
一个堆和一个并查集对应,并且满足并查集中所有没有死的人等于堆中的人 /************************************************************** Pr ...
- bzoj 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle——小根堆+大根堆+贪心
Description 公交车一共经过N(1<=N<=20000)个站点,从站点1一直驶到站点N.K(1<=K<=50000)群奶牛希望搭乘这辆公交车.第i群牛一共有Mi(1& ...
随机推荐
- Graph、DFS、BFS
Graph.java package Graph; import LinearLIst.bag.Bag; import edu.princeton.cs.algs4.In; public class ...
- 浅谈JMX
JMX在Java编程语言中定义了应用程序以及网络管理和监控的体系结构.设计模式.应用程序接口以及服务.通常使用JMX来监控系统的运行状态或管理系统的某些方面,比如清空缓存.重新加载配置文件等 优点是可 ...
- Eclipse连接数据库报错Local variable passwd defined in an enclosing scope must be final or effectively final
其实原因很简单,就是翻译的结果 匿名内部类和局部内部类只能引用外部的fianl变量 把变量变成fianl就行了 第一次知道啊 记小本本.......
- ASP.NET Core如何限制请求频率
原文:ASP.NET Core如何限制请求频率 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.ne ...
- 什么是IOC和什么是AOP,依赖注入(DI)和Ninject,Ninject
我们所需要的是,在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种“需要”,就称为DI(依赖注入,Dependency Injection),和所谓的IoC(控制反转,I ...
- javascript学习方法指南
Javascript看似无限的可能性使得基于HTML和CSS的公共网站成为过去.然而,尽管JavaScript为用户提供了出色的动态体验,但它也为开发人员创建了一个雷区.因此,Javascript搜索 ...
- 如何在cmd命令行中运行Java程序
cmd运行java 有萌新问我怎么用cmd运行Java,他运行报错了,怎么办?如图是他的执行过程: 他说就这一个类,里面包含了main方法怎么会没有加载主类呢. 其实很简单,因为你执行的时候并不能直接 ...
- Linux 下幾種網芳/Samba 目錄的 mount 方式
Linux 下幾種網芳/Samba 目錄的 mount 方式,比較新的 Smaba 只能用 cifs 的 mount 方式. [smbmount] smbmount -o username=&qu ...
- Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported告诉你,你的请求头是application/x- ...
- Mysql设置主库binlog文件自动清理
mysql主库中设置了打开binlog模式后,会在datadir目录下生成大量的日志文件,mysql默认是不会自动清理的,我们来设置下mysql自动清理binlog文件 一.打开mysql [root ...