[NOI2015]荷马史诗 - Huffman树

2023-12-14 14:10

本文主要是介绍[NOI2015]荷马史诗 - Huffman树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

追逐影子的人,自己就是影子。 ——荷马

llison 最近迷上了文学。她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的《荷马史诗》。但是由《奥德赛》和《伊利亚特》组成的鸿篇巨制《荷马史诗》实在是太长了,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 的最短长度。

示例1

输入

4 2
1
1
2
2

输出

12
2

说明

用 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。与最优方案相比,文章的长度相同,但是最长字符串的长度更长一些。

image-20200809155845166

image-20200809155859876

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=1002019;
#define int long long
int n,k,ans,mxd,tot,val[N],v[N];
struct Edge{int to,next;}e[N<<1];
void add(int x,int y){e[++tot].to=y; e[tot].next=v[x]; v[x]=tot;
}
struct node{int id,w,dep;// id :编号, w :权值, dep :子树深度 . node(int a,int b,int c){id=a;w=b;dep=c;};bool operator >(const node &rhs)const{return rhs.w==w?rhs.dep<dep:rhs.w<w;}
};
priority_queue<node,vector<node>,greater<node> > q;
void dfs(int x,int d){ // 统计答案 if(x<=n)ans+=val[x]*d,mxd=max(mxd,d);for(int p=v[x];p;p=e[p].next)dfs(e[p].to,d+1);
}
int read(){int x=0,f=1; char ch=getchar();while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
#undef int
int main()
{#define int long longn=read(); k=read();for(int i=1;i<=n;i++)q.push(node(i,val[i]=read(),0));while((n-1)%(k-1)!=0)q.push(node(++n,0,0));// 插入若干虚拟结点int id=n,n1=n;while(n1-=k-1,n1>=1){int th=0,mx=0; ++id; // 新建编号为 id 的点 th for(int i=1;i<=k;i++,q.pop()){ // 取出 k 个最优元素node nw=q.top(); th+=nw.w;mx=max(mx,nw.dep); add(id,nw.id);} q.push(node(id,th,mx+1)); // 插入该结点 } dfs(id,0); // 统计答案 printf("%lld\n%lld",ans,mxd);return 0;
}

这篇关于[NOI2015]荷马史诗 - Huffman树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/492830

相关文章

数字视频编码概述(熵编码/Huffman编码)

1. 数字视频压缩的必要性和可能性 按ITU-R BT. 601建议,数字化后的输入图像格式为720*576像素,帧频为25帧/s,采样格式为4:2:2,量化精度为8bit, 则数码率:(720 * 576 + 360 * 576 + 360 * 576) * 25帧/s * 8bit = 165.888Mbit/s。 如果视频信号数字化后直接存放在650MB的光盘中,在不考虑音频信号的

数据结构-非线性结构-树形结构:有序树 ->二叉树 ->哈夫曼树 / 霍夫曼树(Huffman Tree)【根据所有叶子节点的权值构造出的 -> 带权值路径长度最短的二叉树,权值较大的结点离根较近】

哈夫曼树概念:给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。 哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。 一、相关概念 二叉树:每个节点最多有2个子树的有序树,两个子树分别称为左子树、右子树。有序的意思是:树有左右之分,不能颠倒 叶子节点:一棵树当中没有子结点的结点称为叶子

Huffman算法简介

Huffman算法是一种基于统计的压缩方法。它的本质就是对文本文件中的字符进行重新编码,对于使用频率越高的字符,其编码也越短。但是任何2个字符的编码,是不能出现向前包含的。也就是说字符A的编码的前段,不可能为字符B的编码。经过编码后的文本文件,主要包含2个部分:Huffman码表部分和压缩内容部分。解压缩的时候,先把Huffman码表取出来,然后对压缩内容部分各个字符进行逐一解码,形成源文件。

huffman树概念、构造方法及huffman编码

概念 Huffman树概念 Huffman树(霍夫曼树),也称为最优二叉树,是一种特殊的二叉树,广泛应用于数据压缩领域。它基于字符出现的频率或概率构建,使得整体的平均编码长度最小,从而达到压缩数据的目的。在Huffman树中,频率或概率越高的字符距离根节点越近,这样可以确保常用字符使用较短的编码,不常用字符使用较长的编码。 Huffman树的构造方法 初始化:将待编码的字符及其频率作为叶子

Huffman算法压缩解压缩(C)

1 概述 Huffman压缩算法是一种基于字符出现频率的编码算法,通过构建Huffman树,将出现频率高的字符用短编码表示,出现频率低的字符用长编码表示,从而实现对数据的压缩。以下是Huffman压缩算法的详细流程: 统计字符频率:遍历待压缩的数据,统计每个字符出现的频率。 构建优先队列:将每个字符及其频率作为一个结点放入优先队列(或最小堆)中,根据字符频率构建一个按频率大小排序的优先队列。 构

Huffman树的建立、字符界面下的显示及序列化(一)

本文主要是Clifford A. Shaffer所著的《Data Structures and Algorithm Analysis in C++》一书中项目设计习题5.7的实现。 Huffman树是一种可以用来压缩文件的技术。为在计算机上存取文件,需要为文件中的每个字符分配一个编码,一般情况下,每个字符的编码长度相同。例如,每个ASCII字符的编码长度为8位。那么,保存一个有着1000个字符的

中文压缩和解码程序设计与实现(huffman)

本项目是利用huffman算法进行中文压缩和解码的设计与实现,huffman算法被证明是最优的结构,可以用于数据压缩 源码 /**************************************************************************************** this function is about to compress a file

【C++】C++ QT实现Huffman编码器与解码器(源码+课程论文+文件)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C++/Python语言 👉公众号👈:测试开发自动化【获取源码+商业合作】 👉荣__誉👈:阿里云博客专家博主、51CTO技术博主 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 C++ QT实现Huffman编码器与解码器(源码+课程论文+文件)【独一无二】 目录 C++ QT实现Huffman

Compression Deep Neural Networks With Pruning, Trained Quantization And Huffman Coding

本次介绍的方法为“深度压缩”,文章来自2016ICLR最佳论文 《Deep Compression: Compression Deep Neural Networks With Pruning, Trained Quantization And Huffman Coding 转自:http://blog.csdn.net/shuzfan/article/details/51383809 (内含多

uvalive 2088 - Entropy(huffman编码)

题目连接:2088 - Entropy 题目大意:给出一个字符串, 包括A~Z和_, 现在要根据字符出现的频率为他们进行编码,要求编码后字节最小, 然后输出字符均为8字节表示时的总字节数, 以及最小的编码方式所需的总字节数,并输出两者的比率, 保留一位小数。 解题思路:huffman编码。 #include <stdio.h>#include <string.h>#