荷馬史詩 NOI2015 解析

2022-05-30 18:00:17 字數 2814 閱讀 8030

比較簡單,這道題需要貪心解決。

不需要任何複雜的資料結構,乙個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=100010

;type rec=record

num,deep:int64;

end;

varn,k,i,j,tot:longint;ans,mxdep:int64;

node,now:rec;

a:array[1..maxn]of

int64;

q:array[1..maxn]of

rec;

procedure swap(var

a,b:rec);

vart:rec;

begin

t:=a; a:=b; b:=t;

end;

procedure

up(x:longint);

begin

while x>1

dobegin

if (q[x].num>q[x div

2].num)or((q[x].num=q[x div

2].num)and(q[x].deep>q[x div

2].deep))//注意多判斷深度

then

break;

swap(q[x],q[x

div2

]); x:=x div2;

end;end

;procedure

down(x:longint);

varlson,rson,son,pd:longint;

begin

while xdo

begin

lson:=2*x; //pd=1

; rson:=2*x+1; //pd=2

; pd:=1;

if lson>tot then

break;

if (lsonand((q[lson].num>q[rson].num)or(q[lson].num=q[rson].num)and(q[lson].deep>q[rson].deep)) then pd:=2;

if pd=1

then son:=lson

else son:=rson;

if (q[x].numor((q[x].num=q[son].num)and(q[x].deepthen

break;

swap(q[x],q[son]);

x:=son;

end;end

;begin

readln(n,k);

for i:=1

to n do

read(a[i]);

if k<>2

then

while n mod (k-1)<>1

dobegin

inc(n); a[n]:=0;

end;//如果不是2叉堆需要初始化保證huffman樹最後一層的元素到達k個,方便操作

tot:=0;

for i:=1

to n do

begin

inc(tot);

q[tot].num:=a[i];

q[tot].deep:=0

; up(tot);

end;//建堆

while tot<>1

dobegin

node.num:=0;node.deep:=0; mxdep:=0

;//k個元素的和、深度、最大深度

for i:=1

to k do

begin

now:=q[1

]; swap(q[

1],q[tot]);

dec(tot);

down(1);

node.num:=node.num+now.num;

mxdep:=max(mxdep,now.deep);

end;//由於是k進製所以需要取出堆中k個元素

ans:=ans+node.num;//累加

node.deep:=mxdep+1

;//深度++

inc(tot);

q[tot]:=node;

up(tot);//放回去

end; writeln(ans);

writeln(mxdep+1

);//列印

end.

NOI2015 荷馬史詩

題面 追逐影子的人,自己就是影子 荷馬 allison 最近迷上了文學。她喜歡在乙個慵懶的午後,細細地品上一杯卡布奇諾,靜靜地閱讀她愛不釋手的 荷馬史詩 但是由 奧德賽 和 伊利亞特 組成的鴻篇巨制 荷馬史詩 實在是太長了,allison 想通過一種編碼方式使得它變得短一些。一部 荷馬史詩 中有n種...

荷馬史詩(NOI2015)提高組

追逐影子的人,自己就是影子 荷馬 allison 最近迷上了文學。她喜歡在乙個慵懶的午後,細細地品上一杯卡布奇諾,靜靜地閱讀她愛不釋手的 荷馬史詩 但是由 奧德賽 和 伊利亞特 組成的鴻篇巨制 荷馬史詩 實在是太長了,allison 想通過一種編碼方式使得它變得短一些。一部 荷馬史詩 中有n種不同的...

NOI 2015 荷馬史詩 (哈夫曼樹)

問題描述 追逐影子的人,自己就是影子。荷馬 allison 最近迷上了文學。她喜歡在乙個慵懶的午後,細細地品上一杯卡布奇諾,靜靜地閱讀她愛不釋手的 荷馬史詩 但是由 奧德賽 和 伊利亞特 組成的鴻篇巨制 荷馬史詩 實在是太長了,allison 想通過一種編碼方式使得它變得短一些。一部 荷馬史詩 中有...