合并果子(哈夫曼树)NOIP2004提高组

简介: 合并果子(哈夫曼树)NOIP2004提高组

在一个果园里,达达已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。


达达决定把所有的果子合成一堆。


每一次合并,达达可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。


可以看出,所有的果子经过 n−1 次合并之后,就只剩下一堆了。


达达在合并果子时总共消耗的体力等于每次合并所耗体力之和。


因为还要花大力气把这些果子搬回家,所以达达在合并果子时要尽可能地节省体力。


假定每个果子重量都为 1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使达达耗费的体力最少,并输出这个最小的体力耗费值。


例如有 3 种果子,数目依次为 1,2,9。


可以先将 1、2堆合并,新堆数目为 3,耗费体力为 3。


接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 12,耗费体力为 12。


所以达达总共耗费体力=3+12=15。


可以证明 15 为最小的体力耗费值。

输入格式

输入包括两行,第一行是一个整数 n,表示果子的种类数。

第二行包含 n 个整数,用空格分隔,第 i 个整数 ai 是第 i 种果子的数目。

输出格式

输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。

输入数据保证这个值小于 2^31。

数据范围

1≤n≤10000,

1≤ai≤20000

输入样例:
1. 3
2. 1 2 9
输出样例:
15

思路:看完题目就知道其实是哈夫曼树的合并过程,而哈夫曼树可以用大根堆来表示,那合并的这个过程用小根堆来模拟,每次取小根堆的top(),进行合并,合并完之后在push()。

这里用小根堆的原因就是因为小根堆的特性就是把最小值放最顶部,而如果用数组去模拟,每次合并之后需要重新sort一遍。

小根堆不需要自己手写,用优先队列priority_queue作为大根堆,因为题目中所有数值全是严格大于0,所以将所有数值取反,最后将结果取反,其效果是一样的

完整代码:

#include <iostream>
#include <queue>
using namespace std;
const int N=10010;
int n;
typedef long long ll;
priority_queue<int> q;
 
int main(){
    cin>>n;
    int res,temp=0;
    for(int i=0;i<n;i++)
    {
        cin>>res;
        q.push(-res);
    }
    res=0;
    while(q.size()>=2){
        temp=q.top();
        q.pop();
        temp=temp+q.top();
        q.pop();
        q.push(temp);
        res+=temp;
    }
    cout<<-res;
}
相关文章
|
9月前
|
算法
【递归搜索回溯专栏】专题二:二叉树中的深搜----求根节点到叶节点数字之和
【递归搜索回溯专栏】专题二:二叉树中的深搜----求根节点到叶节点数字之和
54 0
|
9月前
|
测试技术
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
|
8月前
|
算法 C++
【洛谷 P1090】[NOIP2004 提高组] 合并果子(贪心算法+哈夫曼编码+优先队列)
该编程题目要求设计算法,将不同种类的果子合并成一堆,使得消耗的体力最小。给定果子种类数`n`(1至10000)和每种果子的数量,需输出合并的最小体力值。使用优先队列(最小堆),每次取出两个数量最少的果子堆合并,并更新总体力消耗。样例输入为3种果子(1, 2, 9),输出最小体力耗费为15。提供的AC代码采用C++实现,通过优先队列优化合并顺序。
121 0
|
9月前
|
JavaScript
线性dp之石子合并
线性dp之石子合并
|
9月前
leetcode代码记录(二叉树的最小深度
leetcode代码记录(二叉树的最小深度
34 0
|
9月前
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树2
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树2
|
9月前
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树1
[leedcode]刷题有感 二叉树的深度、节点数量、与平衡二叉树
|
9月前
|
人工智能 算法 BI
【树】【因子数】【数论】【深度优先搜索】2440. 创建价值相同的连通块
【树】【因子数】【数论】【深度优先搜索】2440. 创建价值相同的连通块
|
存储
第二期:链表经典例题(两数相加,删除链表倒数第N个节点,合并两个有序列表)
第二期:链表经典例题(两数相加,删除链表倒数第N个节点,合并两个有序列表)
103 0