P1090 合并果子(哈弗曼树)

题目描述

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

每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n−1n-1n−1 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 111 ,并且已知果子的种类 数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

例如有 333 种果子,数目依次为 111 , 222 , 999 。可以先将 111 、 222 堆合并,新堆数目为 333 ,耗费体力为 333 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 121212 ,耗费体力为 121212 。所以多多总共耗费体力 =3+12=15=3+12=15=3+12=15 。可以证明 151515 为最小的体力耗费值。

输入输出格式

输入格式:

共两行。
第一行是一个整数 n(1≤n≤10000)n(1\leq n\leq 10000)n(1≤n≤10000) ,表示果子的种类数。

第二行包含 nnn 个整数,用空格分隔,第 iii 个整数 ai(1≤ai≤20000)a_i(1\leq a_i\leq 20000)ai?(1≤ai?≤20000) 是第 iii 种果子的数目。

输出格式:

一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 2312^{31}231 。

输入输出样例

输入样例#1:
复制

3
1 2 9

输出样例#1: 复制

15

说明

对于30%的数据,保证有n≤1000n \le 1000n≤1000:

对于50%的数据,保证有n≤5000n \le 5000n≤5000;

对于全部的数据,保证有n≤10000n \le 10000n≤10000。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<cmath>

const int maxn=1e5+5;
typedef long long ll;
using namespace std;
int a[maxn];
int main()
{
    int n;
    cin>>n;
    priority_queue<int,vector<int>,greater<int> >q;
    int x;
    for(int t=0;t<n;t++)
    {
        scanf("%d",&x);
        q.push(x);
    }
    int sum=0;
    while(q.size()>1)
    {
        int a1=q.top();
        q.pop();
        int a2=q.top();
        q.pop();
        //cout<<a1+a2<<endl;
        sum+=(a1+a2);
        q.push(a1+a2);
    }
    cout<<sum<<endl;

} 

原文地址:https://www.cnblogs.com/Staceyacm/p/11224708.html

时间: 2024-08-03 02:03:35

P1090 合并果子(哈弗曼树)的相关文章

哈弗曼树的构建,哈夫曼编码、译码

哈夫曼树的基本概念 哈夫曼树(Huffman Tree),又叫最优二叉树,指的是对于一组具有确定权值的叶子结点的具有最小带权路径长度的二叉树. (1)路劲(Path):从树中的一个结点到另一个结点之间的分支构成两个结点间的路径. (2)路径长度(Path Length):路径上的分支树. (3)树的路径长度(Path Length of Tree):从树的根结点到每个结点的路径长度之和.在结点数目相同的二叉树中,完全二叉树的路径长度最短. (4)结点的权(Weight of  Node):在一些

哈弗曼树的建立

哈弗曼树也称为最优二叉树,它是带权路径长度最短的树,权值越大的结点就离根节点越近.(一般在哈弗曼编码中,权值表示出现的概率,即出现的概率越大,那么访问时的路径就越短). 构建哈弗曼树: 将n个权值构造出n棵只有根节点的树,构成森林. 在森林中选出两个根结点的权值最小的树分别做左右孩子合并一棵新树,且新树的根结点权值为左右结点之和. 从森林中删除选取的两棵树,并将构成的新想树插入到森林中. 构建哈弗曼树的步骤图解如下. 代码实现: //哈弗曼树 #include <stdio.h> #inclu

poj 3253 Fence Repair 【哈弗曼树】+【优先队列】

Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27742   Accepted: 9019 Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000)

【哈弗曼树】HDU 5350 MZL&#39;s munhaff function

通道 题意:根据那个递推式,找找规律即可. 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; typedef long long ll; inline bool rd(int &ret) { char c; int sgn; if(c = getchar(

哈弗曼树及其操作

1.哈弗曼树的节点声明 1 package com.neusoft.Tree; 2 3 public class HuffmanNode { 4 public int weight; 5 //加入哈夫曼树的标志,flag=0表示该节点没有加入哈夫曼树,=1表示加入 6 public int flag; 7 public HuffmanNode parent,lchild,rchild; 8 public HuffmanNode() { 9 this(0); 10 } 11 public Huff

java实现哈弗曼树

O(∩_∩)O~~ 概述 我想学过数据结构的小伙伴一定都认识哈弗曼,这位大神发明了大名鼎鼎的“最优二叉树”,为了纪念他呢,我们称之为“哈弗曼树”.哈弗曼树可以用于哈弗曼编码,编码的话学问可就大了,比如用于压缩,用于密码学等.今天一起来看看哈弗曼树到底是什么东东. 概念 当然,套路之一,首先我们要了解一些基本概念. 1.              路径长度:从树中的一个结点到另一个结点之间的分支构成这两个结点的路径,路径上的分支数目称为路径长度. 2.              树的路径长度:从树

数据结构&amp;&amp;哈弗曼树和哈弗曼编码

1.什么是哈夫曼树和哈弗曼编码 大家来看这样一道面试题(题目来自于<程序员面试宝典>).用二进制来编码字符串"abcdabaa",需要能够根据编码,解码回原来的字符串,最少需要多长的二进制字符串? A.12 B.14 C.18 D.24 解析:典型的哈弗曼编码问题:字符串"abcdabaa"有4个a.2个b.1个c.1个d.构造哈弗曼树如下图所示(图好丑).a编码0(1位),b编码10(2位),d编码111(3位).二进制字符串的总长度为1*4+2*2+

(源码,具体的细节请查阅相关资料)哈弗曼树的构造以及非递归遍历树

写了一点haffman树的创建和二叉树的非递归遍历. 如果编写代码的时候出现了,思维断点,可以借鉴一下, 避免浪费一些不必要的时间. 我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占 位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我 是占位符我是占位符我是占位符我是占位符我是占位符我是 占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符

简单哈弗曼树(Java)

哈夫曼树的实现 1.编码思想 哈夫曼编码是一种变长的编码方案,字符的编码根据使用频率的的不同而长短不一, 使用频率高的字符其编码较短,使用频率低的字符编码较长,从而使所有的编码总长度为最短. 统计原始数据中个新号符号的频率,安频率高低的次序排列 将两个频率最小的相加,作为原本两个节点的父节点,次父节点的频率为子节点之和 重复上述两部,直到和为只剩下一个元素,那么这个元素就是根 2.解码思想 利用Haffman树进行解码,已知一个二进制位串S,从串S的第一位出发,逐位的去匹配二叉树边上标记的0和1