• 【NOI2015T4】荷马史诗-优先队列实现K进制哈夫曼编码+贪心


    测试地址:荷马史诗

    做法:按照题目的定义,就是要求一个最优编码,最优编码就是哈夫曼编码,不懂的可以百度。我们可以通过构造哈夫曼树来找到最优编码,由于原来2进制编码时用到的哈夫曼树是二叉树,所以K进制编码时用到的哈夫曼树就是K叉树。K叉哈夫曼树的构造方法如下:用优先队列维护一个森林,一开始都是单点,存储每棵树的权值(在这道题里就是出现次数),每次从优先队列取出权值最小的K棵树,在它们上面增加一个根,合成一棵新树,新树的权值是K棵树权值的总和,将新树放入优先队列。当最后只剩下一棵树时,这棵树就是要求的哈夫曼树。不过,为了方便处理,由于每次要减少K-1棵树,最后要剩下一棵树,所以我们一开始要添加(K-1)-(N-1)%(K-1)个权值为0的辅助节点。答案可以在构造时同步统计,每次合并树时,答案就增加新树的权值那么多。然而还有第二个问,那么我们只需要再存储每棵树的深度(单点的深度为0),保证优先队列中的元素以权值为第一关键字升序排列,以深度为第二关键字升序排列,每次取出队首的K棵树合并即可。合并后新树的深度就是K棵树中最深的树的深度+1。最后第二个问的答案就是最后一棵树的深度。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    int n,k;
    long long ans,mxlen;
    struct state
    {
      long long val,dep;
      bool operator < (state a) const
      {
        if (val!=a.val) return val>a.val;
    	else return dep>a.dep;
      }
    };
    priority_queue<state> q;
    
    int main()
    {
      scanf("%d%d",&n,&k);
      for(int i=1;i<=n;i++)
      {
        long long a;
    	scanf("%lld",&a);
    	state s;
    	s.val=a,s.dep=0;
        q.push(s);
      }
      int k0=((k-1)-(n-1)%(k-1))%(k-1);
      for(int i=1;i<=k0;i++)
      {
        state s;
    	s.val=s.dep=0;
        q.push(s);
      }
      
      while(!q.empty())
      {
        long long sum=0,mxdep=0;
    	bool flag=0;
        for(int i=1;i<=k;i++)
    	{
    	  state now=q.top();q.pop();
    	  if (i==1&&q.empty()) {mxlen=now.dep;flag=1;break;}
    	  sum+=now.val;
    	  mxdep=max(mxdep,now.dep);
    	}
    	if (!flag)
    	{
    	  state s;
    	  s.val=sum,s.dep=mxdep+1;
    	  q.push(s);
    	  ans+=sum;
    	}
      }
      
      printf("%lld
    %lld",ans,mxlen);
      
      return 0;
    }
    


  • 相关阅读:
    CSAPP bomb实验
    CSAPP y8664实验
    Linux的find基础使用
    redis学习
    cookie
    JavaScript技巧
    如何在网页中使用响应式图像
    10 个常用的 JS 工具库,80% 的项目都在用!
    Vue自定义指令
    巧用 CSS 实现动态线条 Loading 动画
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793728.html
Copyright © 2020-2023  润新知