首页 > 其他分享 >『题解』UVA 12676 Inverting Huffman

『题解』UVA 12676 Inverting Huffman

时间:2022-11-26 21:55:20浏览次数:74  
标签:编码 字符 int 题解 12676 算法 权值 文本 Huffman

题目传送门


题意

静态哈夫曼编码是一种主要用于文本压缩的编码算法。给定一个由 \(N\) 个不同字符组成的特定长度的文本,算法选择 \(N\) 个编码,每个不同的字符一个编码。使用这些编码压缩文本,当选择编码算法构建一个具有 \(N\) 个叶子的二叉树时,对于 \(N \ge 2\),树的构建如下:

  • 对文本中的每个不同字符,构建一个仅包含单个结点的树,并为其分配权值,权值与文本中该字符出现的次数一致。

  • 构建一个包含上述 \(N\) 棵树的集合 \(s\)。

  • 当 \(s\) 包含多于一棵树时:

    (a) 选择最小的权值 \(t_1\in s\),并将其从 \(s\) 中删除;

    (b) 选择最小的权值 \(t_2 \in s\),并将其从 \(s\) 中删除;

    (c) 构建一棵新树 \(t\),\(t_1\)为其左子树,\(t_2\) 为其右子树,并且 \(t\) 的权值为 \(t_1, t_2\) 权值之和;

    (d) 将 \(t\) 加入 \(s\) 集合。

  • 返回保留在 \(s\) 中的唯一一棵树。
    对于文本 "abracadabra",由上述过程生成的树,可以像下图左侧,其中每个内部结点编辑有子树根的权值。请注意获得的树也可以像下图右侧或其它,因为在步骤 3(a), 3(b) 中,结合可能包含几个权值最小的树。

对文本中的每个不同字符,其编码取决于最终树中从根到对应字符的叶子之间的路径,编码的长度是这条路径中的边数(与路径中的内部结点一致)。假设该算法构建的是左侧的树,"r" 的代码长度为 \(3\),"d" 的代码长度为 \(4\)。
根据算法选择的 \(N\) 个代码的长度,找所有字符总数的最小值。


输入格式

输入文件包含多个测试用例,每个测试用例如下所述:

第一行包含一个整数 \(N\)(\(2 \le N \le 50\)),表示文本中出现的不同字符数。

第二行包含 \(N\) 个整数 \(Li\)(\(1 \le Li \le 50\),\(i=1,2,...,N\)),表示由 Huffman 算法生成的不同字符的编码长度。

假设至少存在一棵上述算法构建的树,可以生成具有给定长度的编码。

输出格式

对每个测试用例,输出一行,表示所有字符总数的最小值。


\(Code\)

这个不是简单的求哈夫曼编码,而是反其道而行之,提供了各个字符哈夫曼编码的长度,求文章总字符个数最少是多少个。

我们同样从最底层开始考虑(假设是 $ m $),显然最底层的字符最少出现次数是 $ 1 $。那么 $ m-1 $ 层叶子节点的最小值应该是第 $ m $ 层的最大值。同时 $ m-1 $ 层应该还有一些非叶子节点是有第 $ m $ 层的节点两两合并而来。

我们一层层模拟这个过程即可,用 \(deep_i\) 保存第 \(i\) 层的节点,初始输入中给的叶子全部为 \(0\)。

最后根节点的值就是文章的最小总字符数。

#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
using namespace std;
typedef long long ll;
const int maxn=55;

int n,d[maxn],maxd;
vector<ll> deep[maxn];
ll ans,temp;
int main (){
    while(scanf("%d",&n)!=EOF){
        //清空
        ans=temp=maxd=0;
        for(int i=0;i<=n;i++)deep[i].clear();
        //输入
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            d[x]++;
            deep[x].push_back(0);
            maxd=max(maxd,x);
        }
        //从最下面一层往上计算
        temp=1;
        for(int i=maxd;i>=1;i--){
            for(int j=0;j<SZ(deep[i]);j++){
                if(deep[i][j]==0){
                    deep[i][j]=temp;
                }
            }
            sort(deep[i].begin(),deep[i].end());
            for(int j=0;j<SZ(deep[i]);j+=2){
                deep[i-1].push_back(deep[i][j] + deep[i][j+1]);
            }
            temp=deep[i][SZ(deep[i])-1];
        }
        //输出根节点,即总字符数
        cout<<deep[0][0]<<endl;
    }
    return 0;
}

标签:编码,字符,int,题解,12676,算法,权值,文本,Huffman
From: https://www.cnblogs.com/mrCrazyWolf/p/16928424.html

相关文章

  • 『题解』Codeforces 1743A Password
    Problem现有\(4\)位密码,满足以下条件:给定数位的集合\(S\),密码中没有用到这些数位。密码中恰好包含两个数位,每个数位出现了两次。求符合条件的密码个数。Solution......
  • 『题解』Codeforces 1742C Stripes
    Problem在\(8\times8\)的网格上,轮流染上红色和蓝色。红色只能染一整行。蓝色只能染一整列。问最后用的是哪种颜色。Solution题目说明了至少会染一个条纹,所以我......
  • 『题解』Codeforces 1702A Round Down the Price
    题意这道题其实就是让你求出当前数字与\(10\)的整数幂次的差值(注意不能向上取,只能向下取)。而且题目也标注了\(1\lek\le9\),所以我们可以让\(i\)从\(0\sim9\)......
  • IOS13及以上Fiddler不能抓包问题解决
    iOS 上一般情况下信任HTTPS证书即可抓HTTPS的包(除非APP开启了防止抓包),但最近发现iOS 13以上出现即使安装并信任了证书,当用safari浏览百度时仍出现是否信任该网站......
  • dp完全背包问题解组合问题——零钱兑换
    本题为完全背包问题,遍历容量需要顺序遍历classSolution{public:intchange(intamount,vector<int>&coins){//完全背包顺序遍历//背包容量为a......
  • 题解 P7623 [AHOI2021初中组] 收衣服
    我还在小学的时候以现在初中名义我大五十牛逼参加了这次,然后身败名裂死磕这道题不会,现在觉得自己好傻啊233333显然这是要统计每个区间的贡献,所以我们可以打出来这个暴力,......
  • [蓝桥杯 2022 省 A] 填空问题 题解
    题目传送门这是一道提交答案题,也可以说是一道数学题。第一题我们先来看第一题。由于二维码在纸的中间部分,所以一开始要先裁剪\(4\)刀,这点题目也说了。其次,题目中展......
  • [传智杯 #4 初赛] 竞争得分 题解
    题目传送门这道题主要考察的是"打擂台"算法,也就是求最大或求最小值。就像这样:if(x>maxn)maxn=x;也可以写成这样:maxn=max(maxn,x);最小值同理。然而光......
  • python(牛客)试题解析3 - 困难
    导航一、找到已经最大承重的背包内如何放入最大价值的物品的最优解二、查找一个字符串中包含另外一个字符串(可打乱顺序)的次数三、计算正整数数组从头走到最后一个成员......
  • [传智杯 #4 初赛] 报告赋分 题解
    题目传送门这是一道非常适合新手练习的分支结构题,按照题意模拟即可。1#include<bits/stdc++.h>2usingnamespacestd;3intmain(){4intt;5ci......