• 【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 }
  • 相关阅读:
    leetcode 54. 螺旋矩阵 js高效实现
    leetcode 141. 环形链表 js 实现
    通过 BFC 实现页面布局
    leetcode 1351. 统计有序矩阵中的负数 js实现
    js 实现元素拖拽
    如何在 chrome控制台快速获取某段 html?
    leetcode 160. 相交链表 js 实现
    leetcode 70. 爬楼梯 js实现
    nodejs中事件循环中的执行顺序
    leetcode 300. 最长递增子序列 js 动态规划实现
  • 原文地址:https://www.cnblogs.com/konjak/p/6018180.html
Copyright © 2020-2023  润新知