CCF CSP 2016年12月第4题 压缩编码(区间DP)
来源:互联网 发布:机器人离线编程软件 编辑:程序博客网 时间:2024/04/28 10:54
试题编号:201612-4试题名称:压缩编码时间限制:3.0s内存限制:256.0MB问题描述:
问题描述
给定一段文字,已知单词a1, a2, …, an出现的频率分别t1, t2, …, tn。可以用01串给这些单词编码,即将每个单词与一个01串对应,使得任何一个单词的编码(对应的01串)不是另一个单词编码的前缀,这种编码称为前缀码。
使用前缀码编码一段文字是指将这段文字中的每个单词依次对应到其编码。一段文字经过前缀编码后的长度为:
L=a1的编码长度×t1+a2的编码长度×t2+…+ an的编码长度×tn。
定义一个前缀编码为字典序编码,指对于1 ≤ i < n,ai的编码(对应的01串)的字典序在ai+1编码之前,即a1, a2, …, an的编码是按字典序升序排列的。
例如,文字E A E C D E B C C E C B D B E中, 5个单词A、B、C、D、E出现的频率分别为1, 3, 4, 2, 5,则一种可行的编码方案是A:000, B:001, C:01, D:10, E:11,对应的编码后的01串为1100011011011001010111010011000111,对应的长度L为3×1+3×3+2×4+2×2+2×5=34。
在这个例子中,如果使用哈夫曼(Huffman)编码,对应的编码方案是A:000, B:01, C:10, D:001, E:11,虽然最终文字编码后的总长度只有33,但是这个编码不满足字典序编码的性质,比如C的编码的字典序不在D的编码之前。
在这个例子中,有些人可能会想的另一个字典序编码是A:000, B:001, C:010, D:011, E:1,编码后的文字长度为35。
请找出一个字典序编码,使得文字经过编码后的长度L最小。在输出时,你只需要输出最小的长度L,而不需要输出具体的方案。在上面的例子中,最小的长度L为34。
使用前缀码编码一段文字是指将这段文字中的每个单词依次对应到其编码。一段文字经过前缀编码后的长度为:
L=a1的编码长度×t1+a2的编码长度×t2+…+ an的编码长度×tn。
定义一个前缀编码为字典序编码,指对于1 ≤ i < n,ai的编码(对应的01串)的字典序在ai+1编码之前,即a1, a2, …, an的编码是按字典序升序排列的。
例如,文字E A E C D E B C C E C B D B E中, 5个单词A、B、C、D、E出现的频率分别为1, 3, 4, 2, 5,则一种可行的编码方案是A:000, B:001, C:01, D:10, E:11,对应的编码后的01串为1100011011011001010111010011000111,对应的长度L为3×1+3×3+2×4+2×2+2×5=34。
在这个例子中,如果使用哈夫曼(Huffman)编码,对应的编码方案是A:000, B:01, C:10, D:001, E:11,虽然最终文字编码后的总长度只有33,但是这个编码不满足字典序编码的性质,比如C的编码的字典序不在D的编码之前。
在这个例子中,有些人可能会想的另一个字典序编码是A:000, B:001, C:010, D:011, E:1,编码后的文字长度为35。
请找出一个字典序编码,使得文字经过编码后的长度L最小。在输出时,你只需要输出最小的长度L,而不需要输出具体的方案。在上面的例子中,最小的长度L为34。
输入格式
输入的第一行包含一个整数n,表示单词的数量。
第二行包含n个整数,用空格分隔,分别表示a1, a2, …, an出现的频率,即t1, t2, …, tn。请注意a1, a2, …, an具体是什么单词并不影响本题的解,所以没有输入a1, a2, …, an。
第二行包含n个整数,用空格分隔,分别表示a1, a2, …, an出现的频率,即t1, t2, …, tn。请注意a1, a2, …, an具体是什么单词并不影响本题的解,所以没有输入a1, a2, …, an。
输出格式
输出一个整数,表示文字经过编码后的长度L的最小值。
样例输入
5
1 3 4 2 5
1 3 4 2 5
样例输出
34
样例说明
这个样例就是问题描述中的例子。如果你得到了35,说明你算得有问题,请自行检查自己的算法而不要怀疑是样例输出写错了。
评测用例规模与约定
对于30%的评测用例,1 ≤ n ≤ 10,1 ≤ ti ≤ 20;
对于60%的评测用例,1 ≤ n ≤ 100,1 ≤ ti ≤ 100;
对于100%的评测用例,1 ≤ n ≤ 1000,1 ≤ ti ≤ 10000。
对于60%的评测用例,1 ≤ n ≤ 100,1 ≤ ti ≤ 100;
对于100%的评测用例,1 ≤ n ≤ 1000,1 ≤ ti ≤ 10000。
解题思路:第一次看到这道题的时候,我还是有点懵逼的。本来想着先用Huffman来做,然后再排个序,后来发现事情并没有这么简单。因为要求编码长度最小并且是字典序,而Huffman压缩是每次都合并当前最小的两个数,这就导致了最终编码的无序性,所以只有每次合并相邻的两个数才能保证字典序,每一次合并的代价是相邻两个数之和。诶,这不就是一个石子归并的问题吗,令dp[i, j]表示合并区间[i, j]里的所有数字的最小代价,很显然,dp[i, i] = 0;而dp[i, j] = min(dp[i, j],dp[i, k] + dp[k+1, j] + sum[i, j])。有了状态转移方程,代码就很好写了。
代码如下:
#include <cstdio>#include <climits>#include <cstring>#include <algorithm>#define MAXN 1005using namespace std;int dp[MAXN][MAXN];int sum[MAXN],arr[MAXN];int main(void) { int n; while(scanf("%d",&n) != EOF) { memset(sum,0,sizeof(sum)); for(int i = 1; i <= n; i++) { scanf("%d",&arr[i]); sum[i] = sum[i - 1] + arr[i]; } memset(dp,0,sizeof(dp)); for(int t = 1; t < n; t++) { for(int i = 1; i <= n - t; i++) { int j = i + t; dp[i][j] = INT_MAX; for(int k = i; k < j; k++) { dp[i][j] = min(dp[i][j],dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]); } } } printf("%d\n",dp[1][n]); } return 0;}
阅读全文
0 0
- CCF CSP 2016年12月第4题 压缩编码(区间DP)
- CCF-CSP-2016-12-4 压缩编码
- CCF CSP 2016年12月第2题 工资计算 (模拟 || 打表)
- CCF CSP 2016年9月第4题 交通规划(Dijkstra算法)
- CCF CSP 2016年04月第4题 游戏 (BFS)
- CCF CSP 压缩编码
- CSP 201612-4 压缩编码 【区间DP+四边形不等式优化】
- CCF CSP 2014年12月第2题 Z字型扫描(模拟水题)
- CCF CSP 2016年9月第3题 炉石传说(模拟)
- CCF CSP 2015年12月第3题 画图 (模拟+DFS或BFS)
- CCF CSP 2017年3月第4题 地铁修建(Kruskal算法)
- CCF CSP 2015年03月第4题 网络延迟(求树的直径)
- CCF CSP 2015年9月第4题 高速公路(求连通分量)
- CCF CSP 2014年9月第4题 最优配餐(多源多汇BFS)
- CCF CSP 2014年12月第4题 最优灌溉(并查集+Kruskal算法)
- CCF CSP 201612-4 压缩编码(Java-90分)
- CCF CSP 2014年9月第3题 字符串匹配(strstr函数的应用)
- CCF CSP 2017年3月第2题 学生排队(STL运用)
- 我只是不想丢掉这个课堂作业
- 使用RestTemplate上传文件
- es6入门(五)Iterator以及for ...of
- HttpClient怎么设置连接池等待时间
- Python
- CCF CSP 2016年12月第4题 压缩编码(区间DP)
- Windows访问Ubuntu共享文件夹
- JVM内存参数设置
- mysql函数substring_index的用法
- centos 7 ftp 服务器搭建
- selenium 中PageObject思想学习+部分unittest方法
- 远程桌面到 Ubuntu 虚拟机
- 实用的Eclipse快捷键
- 【JAVA开发之架构专题】10.NIO通信架构