博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Gym100212C Order-Preserving Codes
阅读量:4568 次
发布时间:2019-06-08

本文共 1424 字,大约阅读时间需要 4 分钟。

\(n\) 种元素,给出每个元素的出现次数 \(a_i\) ,求一种 \(01\) 编码方案使得满足以下条件:

  1. 没有一个编码是另一个的前缀
  2. 最小化编码后文本的总长
  3. 编码后按字典序保持原来的顺序

输出编码方案

\(n\leq2000\)

dp,四边形不等式


可以发现若只有前两个限制就是求哈夫曼编码(但这和本题并没有什么关系

\(s_i=\displaystyle\sum_{k=1}^ia_i\)\(f_{i,\ j}\) 表示将区间 \([l,\ r]\) 的元素的编码建树后的最小权重和

\(f_{i,\ j}=\displaystyle\min_{i\leq k<j}\{f_{i,\ k}+f_{k+1,\ j}+s_j-s_{i-1}\}\) ,即将 \([i,\ k]\) 补上 \(0\) ,将 \([k+1,\ j]\) 补上 \(1\) ,这满足字典序递增

可以发现这满足四边形不等式,于是可以优化到 \(O(n^2)\)

时间复杂度 \(O(n^2)\)

代码

#include 
using namespace std;typedef long long ll;const int maxn = 2010;string s;int n, pos[maxn][maxn];ll sum[maxn], f[maxn][maxn];void print(int l, int r) { if (l == r) { cout << s << endl; return; } s += '0', print(l, pos[l][r]), s.pop_back(); s += '1', print(pos[l][r] + 1, r), s.pop_back();}int main() { freopen("codes.in", "r", stdin); freopen("codes.out", "w", stdout); scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%I64d", sum + i); pos[i][i] = i, sum[i] += sum[i - 1]; } for (int i = 2; i <= n; i++) { for (int j = 1; i + j - 1 <= n; j++) { int l = j, r = i + j - 1; for (int k = pos[l][r - 1]; k <= pos[l + 1][r]; k++) { if (!pos[l][r] || f[l][k] + f[k + 1][r] < f[l][r]) { f[l][r] = f[l][k] + f[k + 1][r], pos[l][r] = k; } } f[l][r] += sum[r] - sum[l - 1]; } } print(1, n); fclose(stdin), fclose(stdout); return 0;}

转载于:https://www.cnblogs.com/Juanzhang/p/11275034.html

你可能感兴趣的文章
Oracle SQL 基本操作之 用户权限管理方法
查看>>
Java获取系统默认浏览器打开链接
查看>>
.NET I/O 学习笔记:对文件和目录进行解压缩操作
查看>>
Windows Phone笔记(4)图片操作
查看>>
NIM游戏
查看>>
自己动手Jquery插件
查看>>
DS博客作业08--课程总结
查看>>
form表单提交数据到servlet的action=" "路径问题
查看>>
你是否经常忘记网站上的各种密码?分享个密码管理软件LastPass
查看>>
Matlab作图时各种奇怪的问题解决(随时更新)
查看>>
Ubuntu脚本修改IP信息
查看>>
数组方法
查看>>
excel2016中怎么开启宏?excel2016开启宏的步骤
查看>>
mac 电脑有关 操作(删除废弃喽文件)
查看>>
python中的re模块,常用函数介绍
查看>>
kvm配置虚拟机[待整理]
查看>>
Hadoop Pig
查看>>
ll的命令后面的字段详解
查看>>
Delphi中Templates代码模板添加注意事项
查看>>
微信页面控制分享
查看>>