• 洛谷 P2168 [NOI2015]荷马史诗(Huffman树|编码)


    题目链接:https://www.luogu.com.cn/problem/P2168

    哈夫曼编码:

    有n个字符,a,b,c,...,每个字符都有一个频率,$f_a,f_b,f_c...$,用k进制数表示字符a,b,c...

    设计编码,使得总长度Len最短,其中$Len=f_a imes l_a+f_b imes l_b...$

    不难发现,如果每个字符都有自己的表达方式,那么任意两个编码之间不能是对方的前缀,表现在树上就是不能是它的祖先(不在到根节点的路径上)。

    性质:1.字符是叶节点。

       2.非叶节点有k个子节点。(这样一定是最优的)

       2‘.非叶节点中子节点数量不是k的至多有一个。(当(n-1)%(k-1)==0时没有)

        所以可以添加一些(k-1-(n-1)%(k-1))f为0的字符,使其满足性质2,且不会产生影响。

    所以在k进制下,最优的操作就是每次取前k个最小的,合并。

    例题:

    1.合并果子

    题目链接:https://www.luogu.com.cn/problem/P1090

    其实可以看成是一个2进制下的哈夫曼编码问题,搬运花费即为频率,每次合并取前两个最小的。

    2.荷马史诗

    题目链接:https://www.luogu.com.cn/problem/P2168

     k进制下的哈夫曼编码问题。首先看能否满足性质二,不满足则用w为0的字符补全,然后每次取k个合并(想哈夫曼树),即得答案。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long ll;
     7 ll n,k,cnt,sum,ans;
     8 struct node{
     9     ll w,h;
    10 };
    11 bool operator<(node a,node b){
    12     if(a.w!=b.w) return a.w>b.w;
    13     return a.h>b.h;
    14 }
    15 priority_queue<node> q;
    16 int main(){
    17     scanf("%lld%lld",&n,&k);
    18     for(int i=1;i<=n;i++){
    19         node t;
    20         scanf("%lld",&t.w);
    21         t.h=1;
    22         q.push(t);
    23     }
    24     ll top=0;
    25     if((n-1)%(k-1)!=0){
    26         int t=k-1-(n-1)%(k-1);
    27         top+=t;
    28         for(int i=1;i<=t;i++){
    29             node t;
    30             t.w=0;t.h=1;
    31             q.push(t);
    32         }
    33     }
    34     top+=n;
    35     while(top!=1){
    36         ll maxh=0;
    37         sum=0;
    38         for(int i=1;i<=k;i++){
    39             node t;
    40             t=q.top();
    41             q.pop();
    42             maxh=max(maxh,t.h);
    43             sum+=t.w;
    44         }
    45         ans+=sum;
    46         node t;
    47         t.w=sum; t.h=maxh+1;
    48         q.push(t);
    49         top-=k-1;
    50     }
    51     printf("%lld
    %lld",ans,q.top().h-1);
    52     return 0;
    53 }
    AC代码
  • 相关阅读:
    SQLyog
    远程连接设置
    [转]Oracle/Altibase数据库中Sequence的用法
    worklight 初识
    C# Excel
    C#+AE 叠加分析
    Model Buider中 List和Series的区别[转]
    动态分段
    优化工具箱概述
    创建栅格数据
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13760110.html
Copyright © 2020-2023  润新知