• 【uva 10954】Add All(算法效率--Huffman编码+优先队列)


    题意:有N个数,每次选2个数合并为1个数,操作的开销就是这个新的数。直到只剩下1个数,问最小总开销。

    解法:合并的操作可以转化为二叉树上的操作【建模】,每次选两棵根树合并成一棵新树,新树的根权值等于两棵合并前树的根权值和(也与Huffman编码的建立过程类似,选权值最小的两棵树)。

    这样总开销就是除了叶子结点的权值和  =》 每个叶子结点的权值*层数(根节点层数为0)之和  =》 WPL(树的所有叶子节点的带权路径长度之和,即该节点到根节点路径长度与节点上权的乘积之和)。

    而Huffman树就是带权路径长度WPL最短的二叉树,又称最优二叉树。这样建树WPL就最短的原因很明显了,由于n个父亲节点的哈夫曼树含有2n-1个节点,没有度为1的节点,那么叶子结点数确定了,每层的结点数也确定了,那么权值大的点肯定深度越小越好,权值小的点肯定相对来说深度越大越好,这样建树的WPL就一定是最小的。

    于是我们用优先队列来做每次合并权值最小的2个数的操作。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<queue>
     7 using namespace std;
     8 const int N=5010,D=(int)1e5+10;
     9 
    10 priority_queue<int,vector<int>,greater<int> > q;//使优先队列从小到大排列;不能>>连起来,中间要有空格
    11 int main()
    12 {
    13     int n,x,y,h,i;
    14     while (~scanf("%d",&n))
    15     {
    16       if (!n) break;
    17       while (!q.empty()) q.pop();
    18       for (i=1;i<=n;i++) scanf("%d",&x),q.push(x);
    19       h=0;
    20       for (i=1;i<n;i++)
    21       {
    22         x=q.top(),q.pop();
    23         y=q.top(),q.pop();
    24         q.push(x+y), h+=x+y;
    25       }
    26       printf("%d
    ",h);
    27     }
    28     return 0;
    29 }
  • 相关阅读:
    难以理解的二分查找
    程序设计第七次作业——关于计算器的总结
    程序设计第六次作业——计算器(可视化界面)
    课堂作业——1025反转链表
    程序设计第五次作业——计算器(调用文件输入输出)
    circle area
    程序设计第四次作业——计算器第二步(计算)
    第三次作业代码规范修改
    解决Type 'UnityEngine.Component' does not support slicing
    mactype支持qq浏览器
  • 原文地址:https://www.cnblogs.com/konjak/p/6018180.html
Copyright © 2020-2023  润新知