【代码超详解】CometOJ C1272 [JSOI2015]套娃(贪心 + multiset)

一、题目描述

在这里插入图片描述

二、算法分析说明与代码编写指导

本指导是根据 https://www.cnblogs.com/Khada-Jhin/p/10461734.html 改写并扩充的。
设每个套娃mi有三个属性O,I,B,分别代表套娃 i 的外径、内径和好看度。
在没有将任何套娃套入之前,先统计不满意度 d = ∑(mi.O × Bi),i = 1,2,……,N。
如果要让总的不满意度 d 尽可能小,且已知一个套娃内部不可以并排套入多个套娃,那么应当尽量把每个套娃都套入外径尽可能逼近其内径的套娃。易知把一个外径尽可能大的套娃套入后不会影响其它套娃的嵌套,所以可以采用贪心算法,即让每一次嵌套减少的不满意度最大。嵌套时要先从好看度高的套娃开始。
输入时只需要把套娃的外径放入多重集 s 中,输入完毕后先对套娃按好看度排序。
集合默认是升序排列的。从好看度高的套娃开始,在集合中用 lower_bound 成员函数查找第一个大于等于 当前正在尝试嵌套的套娃的内径 的外径,然后将迭代器递减 1 次,就得到了小于 当前正在尝试嵌套的套娃的内径 的最大外径。扣除相应的不满意度,并将这个找到的值删除,就完成了对本次嵌套过程的模拟。但是要注意,查找可能找到 *s.begin(),即正在尝试嵌套的套娃是所有套娃中外径最小的,此时不能将任何套娃嵌入这个套娃中,直接跳过。
对每个套娃都尝试处理完毕后,输出剩余的不满意度 d。

三、AC 代码

#include<cstdio>
#include<algorithm>
#include<set>
#pragma warning(disable:4996)
using namespace std;
struct matryoshka { unsigned long long O, I, B; };
unsigned N; matryoshka m[200000]; multiset<unsigned long long> s; unsigned long long d;
multiset<unsigned long long>::iterator I;
inline bool cmpB(const matryoshka& lhs, const matryoshka& rhs) {
	return lhs.B > rhs.B;
}
int main() {
	scanf("%u", &N);
	for (unsigned i = 0; i < N; ++i) {
		scanf("%llu%llu%llu", &m[i].O, &m[i].I, &m[i].B); d += m[i].I * m[i].B; s.emplace(m[i].O);
	}
	sort(m, m + N, cmpB);
	for (unsigned i = 0; i < N; ++i) {
		I = s.lower_bound(m[i].I);
		if (I != s.begin()) {
			--I; d -= *I * m[i].B; s.erase(I);
		}
	}
	printf("%llu\n", d);
	return 0;
}
发布了214 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/COFACTOR/article/details/104142801
今日推荐