题目

题目链接:荷马史诗

题目描述:
追逐影子的人,自己就是影子。 ——荷马

Allison 最近迷上了文学。她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的《荷马史诗》。但是由《奥德赛》和《伊利亚特》组成的鸿篇巨制《荷马史诗》实在是太长了,Allison 想通过一种编码方式使得它变得短一些。
一部《荷马史诗》中有 n 种不同的单词,从 1 到 n 进行编号。其中第 i 种单词出现的总次数为 wi。Allison 想要用 k 进制串 si 来替换第 i 种单词,使得其满足如下要求:
对于任意的 1≤i,j≤n,i≠j,都有:si 不是 sj 的前缀。
现在 Allison 想要知道,如何选择 si,才能使替换以后得到的新的《荷马史诗》长度最小。在确保总长度最小的情况下,Allison 还想知道最长的 si 的最短长度是多少?
一个字符串被称为 k 进制字符串,当且仅当它的每个字符是 0 到 k−1 之间(包括 0 和 k−1)的整数。
字符串 Str1 被称为字符串 Str2 的前缀,当且仅当:存在 1≤t≤m,使得 Str1=Str2[1…t]。其中,m 是字符串 Str2 的长度,Str2[1…t] 表示 Str2 的前 t 个字符组成的字符串。

输入
输入文件的第 1 行包含 2 个正整数 n,k,中间用单个空格隔开,表示共有 n 种单词,需要使用 k 进制字符串进行替换。

接下来 n 行,第 i+1 行包含 1 个非负整数 wi,表示第 i 种单词的出现次数。

输出
输出文件包括 2 行。

第 1 行输出 1 个整数,为《荷马史诗》经过重新编码以后的最短长度。
第 2 行输出 1 个整数,为保证最短总长度的情况下,最长字符串 si 的最短长度。

Hint
用 X(k) 表示 X 是以 k 进制表示的字符串。

一种最优方案:令 00(2) 替换第 1 种单词,01(2) 替换第 2 种单词,10(2) 替换第 3 种单词,11(2) 替换第 4 种单词。在这种方案下,编码以后的最短长度为:

1×2+1×2+2×2+2×2=12

最长字符串 si 的长度为 2。

一种非最优方案:令 000(2) 替换第 1 种单词,001(2) 替换第 2 种单词,01(2) 替换第 3 种单词,1(2) 替换第 4 种单词。在这种方案下,编码以后的最短长度为:

1×3+1×3+2×2+2×1=12

最长字符串 si 的长度为 3。与最优方案相比,文章的长度相同,但是最长字符串的长度更长一些。

对于所有数据,保证 2≤n≤100000,2≤k≤9。

选手请注意使用 64 位整数进行输入输出、存储和计算。

分析

这个题由于老师给的时候就标注了K叉哈夫曼树
所以避免了很多弯路
如果想不到哈夫曼树,可能就比较难搞
关于哈夫曼树,就不多加解释了

我们已经处理过2叉的哈夫曼树了,那么其实K叉树也是同样的处理方法。
但是这个题有一个深度要求,我们看题就会发现深度这个要求,编码短就要求深度小,所以又怎么处理呢

说实话,我不会。
不会也得会
于是去看了大佬们的解题思路
用优先队列,把深度作为第二关键字
于是C++学的不咋滴的我又开始优先队列咋用
我只用过队列模板啊亲

所以先讲下整体思路:
将每个元素放入优先队列,优先队列会根据优先级进行出队,那么我们就能保证每次出队的是权重最小的。
那么深度又怎么处理呢?
优先队列可设置第二关键字,即在权重相同的情况下判断深度。这样深度也解决了。

优先队列
我自己也不是很会,看了这个Archger的优先队列博客,我觉得还挺好的,不会优先队列的娃可以先看一下:优先队列详解

好了,假装自己会了优先队列,那么问题解决了

上代码

代码实现


#include<stdio.h>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int main()
{priority_queue<pair<long long int,int> >q;//一定要用空格隔开否则会判断为右移报错//优先队列,pair用法是先比较第一个参数长度,相同的话比较第二个参数深度 int n,m,i;long long int x,ans=0;scanf("%d %d",&n,&m);//n个结点,m个叉 for (i=0;i<n;i++){scanf("%lld",&x);q.push(make_pair(-x,-1));//这里优先队列默认优先选大的,可以用结构体然后自定义//但这里使用的pair就将关键字取负值 ,就可以直接使用 }while((n-1)%(m-1)>0){//判断根节点能不能构成m叉树 n++;q.push(make_pair(0,-1));//不能构成就补0结点 }while(q.size()>1){//队列中最后剩的元素就是我们要求的值 long long int w=0,d=0;for(i=0;i<m;i++){//每次取优先值前m个 w-=q.top().first;//因为是负值所以减负负得正,所以这里w是正值,如果用的自定义加就行了 if(d<-q.top().second){//深度要么加深要么不变 d=-q.top().second;}q.pop();}ans+=w;// 直接加上就可以了 q.push(make_pair(-w,-d-1));//依旧负值进队 }printf("%lld\n%d\n",ans,-q.top().second-1);return 0;
}

还可以自定义写优先队,这样就不用取负值了,但我懒,大家可以自己找找。

算法设计——荷马史诗(K叉哈夫曼 贪心)相关推荐

  1. 荷马史诗【k叉哈夫曼树】

    题目描述 追逐影子的人,自己就是影子. --荷马 达达最近迷上了文学. 她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>. 但是由<奥德赛>和 ...

  2. K叉哈夫曼树构造方法 O(N)

    带权路径:是树中所有的叶结点的权值乘上其到根结点的路径长度. 哈夫曼树就是带权路径最小的树. 有n个数(即n个叶子节点),构造k叉(k>=2)哈夫曼树的方法: 构造哈夫曼树,其实就是不停的&qu ...

  3. 哈夫曼树+K叉哈夫曼树

    目录 基本概念 构造方法 证明 代码 k叉哈夫曼树 例题 基本概念 问题:给定n个权值,作为n个叶结点,构造一棵二叉树,而这棵树的特点是,有n个叶节点,叶节点的值为给定的权值.而内部节点的值为子树的权 ...

  4. 【HDU - 5884】Sort(k叉哈夫曼树,优化tricks,两个队列代替优先队列)

    题干: Recently, Bob has just learnt a naive sorting algorithm: merge sort. Now, Bob receives a task fr ...

  5. 两个队列+k叉哈夫曼树 HDU 5884

    1 // 两个队列+k叉哈夫曼树 HDU 5884 2 // camp题解: 3 // 题意:nn个有序序列的归并排序.每次可以选择不超过kk个序列进行合并,合并代价为这些序列的长度和.总的合并代价不 ...

  6. 【BZOJ4198】荷马史诗,贪心之k叉哈夫曼树

    传送门 思路: 很早以前听说过这个题 据说是一个很强的贪心(?) 然后一上来就往贪心上去想--(其实一开始知道算法不是很好,因为你不会走弯路了) 发现这玩意好像是个合并果子的模型-- 也不知道是怎么转 ...

  7. bzoj 4198 [ Noi 2015 ] 荷马史诗 —— 哈夫曼编码(k叉哈夫曼树)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4198 第一次写哈夫曼树!看了很多博客. 哈夫曼树 & 哈夫曼编码:https://w ...

  8. 周末狂欢赛4(1-02E. JM的西伯利亚特快专递,寿司晚宴,荷马史诗)

    文章目录 T1:1-02E. JM的西伯利亚特快专递 题目 题解 code T2:寿司晚宴 题目 题解 code T3:荷马史诗 题目 题解 code T1:1-02E. JM的西伯利亚特快专递 题目 ...

  9. [Huffman树] aw149. 荷马史诗(哈夫曼模型+贪心)

    文章目录 1. 题目来源 2. 题目解析 1. 题目来源 链接:149. 荷马史诗 2. 题目解析 k叉哈夫曼树问题. n 个叶子节点合并成 1 个点,总共合并减少 n-1 个点,每次合并都会减少 ( ...

  10. 算法进阶指南:0x17:荷马史诗

    原题链接 追逐影子的人,自己就是影子. --荷马 达达最近迷上了文学. 她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>. 但是由<奥德赛>和 ...

最新文章

  1. SAP S/4HANA现金管理之变
  2. webpack2诸类事宜
  3. 动态规划(Dynamic Programming)例题步骤详解
  4. 访问chm文件出现“已取消到该网页的导航”的解决方法
  5. 常用UI控件之UIControl
  6. Ubuntu 配置 Tomcat
  7. Linux合上笔记本不进入休眠模式
  8. 使用单元测试驱动开发的方式编写flask应用
  9. 计算机网络-自顶向下方法(7th) 第一章 Review Questions 中英对照
  10. 用c语言编写成绩单由高到低,C语言程序设计实验.doc
  11. mysql使用GROUP BY分组实现取前N条记录的方法或最近几条消费记录
  12. 数据分析师——软件篇
  13. mysql可视化工具
  14. Arduino-定义串口
  15. VLC相关参数中文说明!
  16. 并联串联混合的电压和电流_初中物理归纳并联和串联的区别
  17. 分享一大波高清电子元器件矢量图,速速下载收藏!
  18. iOS:基于Photos框架的图片选择器以及创建自定义相册
  19. SpringBoot集成Nacos
  20. 信捷PLC以太网通讯数据采集解决方案

热门文章

  1. 美团网2015秋季校园招聘面试题(上)
  2. CodeForces 128A Statues 简单搜索
  3. 5种骗你跳槽的谣言,千万别信!
  4. cd rom是计算机的,CD-ROM是什么意思,CD-ROM是什么意思
  5. 搜狗拼音输入法自定义格式的时间和日期并快捷键触发
  6. ThinkPHP5在线问答系统
  7. cisco 路由器 ADSL拨号上网配置
  8. javaweb之统计网站访问量小案例
  9. 华硕笔记本电脑重装系统教程,华硕笔记本系统重装教程
  10. “阀值”与“阈值”的区别