比较简单,这道题需要贪心解决。

不需要任何复杂的数据结构,一个luo的堆就足够了。

本题的意思就是:给定n种单词及在文本中各自出现的频率,要求利用二进制串对其进行前缀编码,使得压缩后的文本长度最短。

改用k进制串?最长的单个单词编码最短?

我们知道有个叫huffman编码的东西就是来解决这类编码问题的。所以尝试用huffman思想去解题。

如果编码的进制是2进制就好了,但是题目的数据只有少部分是2进制编码的,

所以我们要仿造二叉形式huffman一次弹出两个(最小值)成k叉一次弹出k个(最小值);

二叉堆来实现(不是用k叉堆,这样做时间复杂度太高且不易实现)

每一次弹出最值时就是连续取二叉堆的前k个数就可以了。

堆中保存Huffman树中串出现频率和,以及Huffman树的深度;

比较时先比较频率和,再比较深度(不可不比,要保证Huffman树高最小);

每次合并时,ans都要加上合并后长度(要不然求的是串频率和),而深度在取最大后再插入时要加1;

当堆中只有一个元素时退出,这时,ans和该元素深度即为答案;

注意到初始化堆的时候最后一层到不了k个怎么办?

初始化时注意各元素深度为0,若n!≡1mod(k-1),那么补齐n,增加的新元素频率为0(显然),深度为0;

堆的建立就不详细说了。

uses math;
const maxn=;
type rec=record
num,deep:int64;
end;
var n,k,i,j,tot:longint;ans,mxdep:int64;
node,now:rec;
a:array[..maxn]of int64;
q:array[..maxn]of rec;
procedure swap(var a,b:rec);
var t:rec;
begin
t:=a; a:=b; b:=t;
end;
procedure up(x:longint);
begin
while x> do begin
if (q[x].num>q[x div ].num)or((q[x].num=q[x div ].num)and(q[x].deep>q[x div ].deep))//注意多判断深度
then break;
swap(q[x],q[x div ]);
x:=x div ;
end;
end;
procedure down(x:longint);
var lson,rson,son,pd:longint;
begin
while x<tot do begin
lson:=*x; //pd=;
rson:=*x+; //pd=;
pd:=;
if lson>tot then break;
if (lson<tot)and((q[lson].num>q[rson].num)or(q[lson].num=q[rson].num)and(q[lson].deep>q[rson].deep)) then pd:=;
if pd= then son:=lson
else son:=rson;
if (q[x].num<q[son].num)or((q[x].num=q[son].num)and(q[x].deep<q[son].deep)) then break;
swap(q[x],q[son]);
x:=son;
end;
end;
begin
readln(n,k);
for i:= to n do read(a[i]);
if k<> then
while n mod (k-)<> do begin
inc(n); a[n]:=;
end;//如果不是2叉堆需要初始化保证huffman树最后一层的元素到达k个,方便操作
tot:=;
for i:= to n do begin
inc(tot);
q[tot].num:=a[i];
q[tot].deep:=;
up(tot);
end;//建堆
while tot<> do begin
node.num:=;node.deep:=; mxdep:=;//k个元素的和、深度、最大深度
for i:= to k do begin
now:=q[];
swap(q[],q[tot]);
dec(tot);
down();
node.num:=node.num+now.num;
mxdep:=max(mxdep,now.deep);
end;//由于是k进制所以需要取出堆中k个元素
ans:=ans+node.num;//累加
node.deep:=mxdep+;//深度++
inc(tot);
q[tot]:=node;
up(tot);//放回去
end;
writeln(ans);
writeln(mxdep+);//打印
end.

最新文章

  1. oracle分页
  2. 网络之OSI七层模型
  3. 修改linux的最大文件句柄数限制
  4. SBT Assembly - Deduplicate error &amp; Exclude error
  5. QThread
  6. HTTP中Get与Post的区别
  7. WebBrowser 中遍历所有的frames
  8. DIV实现纵向滚动条overflow-y
  9. YTU 2972: C语言习题5.24--文件操作1
  10. 国内银行CNAPS CODE 查询
  11. ListView的自动循环滚动显示
  12. 第一章 :绪论-Twitter数据的收集和处理
  13. 判断richtextbox选中的是否为图片
  14. TDirectory.GetAttributes、TDirectory.SetAttributes获取和设置文件夹属性
  15. 查询数据库返回List&lt;Entity&gt;问题
  16. UVA 1619 Feel Good(DP)
  17. Python自然语言处理学习笔记之信息提取步骤&amp;分块(chunking)
  18. MySQLorder by用法
  19. 新年第一个目标一张表盘串讲所有canves的知识点
  20. vim快捷键与vi

热门文章

  1. 20155336虎光元 Exp1PC平台逆向破解及Bof基础实践
  2. python 算法面试题
  3. SpringBoot配置Aop笔记【例子】
  4. css修改select下拉列表的默认样式
  5. Ubuntu16.04+Java8+Mysql5.7+Tomcat8.5服务器环境配置
  6. Appium+Python3+ Android入门
  7. PAT甲题题解-1029. Median (25)-求两序列的中位数,题目更新了之后不水了
  8. Hybrid APP基础篇(二)-&gt;Native、Hybrid、React Native、Web App方案的分析比较
  9. 作业 20181204-5 Final阶段贡献分配规则及实施
  10. 每日scrum(6)