【ybt高效进阶3-1-5】【POJ 1456】超市购物 / Supermarket

这篇博客介绍了如何运用贪心算法解决一个关于商品销售的问题。具体来说,给定一组商品,每件商品都有价值和最晚销售日期,每天只能销售一件商品,目标是最大化总价值。博主首先通过将商品按最晚销售日期降序、价值升序排序,然后利用优先队列(堆)在每个时间点选择未销售过的商品中价值最大的进行销售。此外,博主还提到了可以使用并查集作为替代解法,并提供了代码实现。
摘要由CSDN通过智能技术生成

超市购物 / Supermarket

题目链接:ybt高效进阶3-1-5 / POJ 1456

题目大意

有一些商品,每个有价值和最晚卖出时间。
一天只能选一个卖出。
问你最大价值。

思路

这道题我们考虑贪心。

你想,一个东西它最晚卖出时间是 x x x,那它就只能在 1 ∼ x 1\sim x 1x 的时间点的其中一个卖出。

那我们发现我们把时间 x x x 往前移的时候,在时间 x x x 之后能卖的东西就越来越多。
那我们想想,在时间往前移一个单位的时候,在新出现的时间卖什么最好呢?

不是这个时间结束的里面价值最大的,而是在这个时间之后能买的东西中没有被选过的东西中价值最大的。

那怎么实现呢?
我们考虑用堆。

先按最晚卖出时间从后往前排序,如果一样就按价值从大到小排。
然后枚举每个物品,把它放进堆里面。然后它比前面一个东西的最晚卖出时间早了,早了多少就把堆上面的多少个东西卖出。(其实意思就是在中间空的每个时间点都选一个最优的东西卖出)
当然,如果堆里面没东西,就是能卖的都卖完了,就可以直接不卖了。

有一点就是记得把 1 ∼ x 1\sim x 1x 这段时间也要卖东西( x x x 是最早的最晚卖出时间),因为这段时间也可以卖东西,而且什么都可以卖。

不过这道题好像有并查集的做法。
我好像之间还用并查集的做法做过。(用堆写完才发现的)
如果想看并查集的做法可以点击下面的链接跳转:
https://blog.csdn.net/weixin_43346722/article/details/90299744

代码

#include<queue> 
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

struct node {
	int x, t;
}a[10001];
int n;
long long ans;
priority_queue <int, vector<int>, less<int> > q;

bool cmp(node x, node y) {
	if (x.t != y.t) return x.t > y.t;
	return x.x > y.x;
}

int main() {
	while (scanf("%d", &n) != EOF) {
		while (!q.empty()) q.pop();
		memset(a, 0, sizeof(a));
		
		for (int i = 1; i <= n; i++)
			scanf("%d %d", &a[i].x, &a[i].t);
		
		sort(a + 1, a + n + 1, cmp);
		//按卖出时间从后往前排序,如果卖出时间相同,那就把价值大的放在前面
		
		ans = 1ll * a[1].x;
		for (int i = 2; i <= n; i++) {
			q.push(a[i].x);
			if (a[i].t != a[i - 1].t)//有时间给你选
				for (int j = 1; j <= a[i - 1].t - a[i].t; j++) {
					if (q.empty()) break;
					ans += 1ll * q.top();//不停的选可以选的价值最大的
					q.pop();
				}
		}
		for (int i = a[n].t - 1; i >= 1; i--) {//记得统计 1 时间到最早结束时间卖的东西的价值
			if (q.empty()) break;
			ans += 1ll * q.top();
			q.pop(); 
		}
		
		printf("%lld\n", ans);
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值