洛谷 P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G 题解

目录

题目

思路

代码

尾声


题目

题目传送门


思路


首先,这道题有一个很明显的贪心

就是每次取最两个最小值

比如

1 2 9

则先把 1 和 2 合在一起,代价为 3,再取 3 和 9 合一起,代价为 12,最后把 3 和 12 加起来就是正确答案 15 了

想证明很简单:最小加次小一定比其他组合都小,这样每次代价就最小了

但还有一个问题,就是每次取最小和次小,再把他们的和送回去,然后再排一趟序,很容易就超时吧

所以我们就要用到优先队列 priority_queue 了

这个东西是可以自动排序的 STL大法好

它是由堆实现的,默认是大根堆,所以队首是最大值,我们就需要把他调成最小值

怎么调呢,看这里:priority_queue <int, vector<int>, greater<int> > pq;(如果你想要大根堆,就可以省略后两个参数了)

如果你在考场上忘了 greater 怎么拼,告诉你一个绝妙方法:比如压 a 的时候就压 -a 这样最大值就变成了最小值(比如 1 2 3 ,最大值为 3,如果压 -3 ,他就变成了最小值,而最大值就变成了 -1)取的时候就也用它的相反数就行了

这样每次取队首两个数,把他们加起来再压回去就行了

(具体请参考下方代码)

代码

#include <iostream>										// 输入输出流头文件 
#include <queue>										// 优先队列需要的头文件 
#include <vector>										// 优先队列的第二个参数动态数组 vector 的头文件 
using namespace std;

priority_queue <int, vector<int>, greater<int> > pq;	// 维护一个小根堆 
int n, a, ans;

int main() {
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> a;
		pq.push(a);										// 输入到小根堆里 
	}
	while(pq.size() > 1) {								// 只剩一堆的时候就结束 
		int x, y;
		x = pq.top();									// 取出队首两个元素 
		pq.pop();
		y = pq.top();
		pq.pop();
		ans += x + y;									// 相加压回去并更新答案 
		pq.push(x + y);
	}
	cout << ans << endl;								// 输出答案 
	
	return 0;
}


尾声


如果这篇题解对您(或您的团队)有帮助的话,就帮忙点个赞,加个关注!

最后,祝您(或您的团队)在 OI 的路上一路顺风!!!

┬┴┬┴┤・ω・)ノ Bye~Bye~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值