压缩编码(区间dp)

题意

数据范围

\(1 \leq n \leq 1000\)
\(1 \leq t_i \leq 10000\)

思路

这道题首先想到的Huffman树,但是因为有字典序的限制,因此字母(叶子节点)在编码树中也应该是从左到右排好的(字典序最小的在最左边)。

对Huffman树的策略进行魔改,发现得到的不是正确答案,因此考虑将正确答案的树画出来。发现,其实这是个区间dp问题,因为排列顺序固定。

将根节点作为分界点,算出左子树的最小值,算出右子树的最小值。根节点比左右子树高一层,因此整棵树的最小值就是:左子树最小值+右子树最小值+字母频率之和。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;

int n;
int a[N];
int s[N];
int f[N][N];

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i];
    for(int k = 2; k <= n; k ++) {
        for(int i = 1; i + k - 1 <= n; i ++) {
            int l = i, r = i + k - 1;
            f[l][r] = 1e9;
            for(int j = l; j < r; j ++) {
                f[l][r] = min(f[l][r], f[l][j] + f[j + 1][r] + s[r] - s[l - 1]);
            }
        }
    }
    printf("%d\n", f[1][n]);
    return 0;
}
posted @ 2021-03-10 19:05  pbc的成长之路  阅读(93)  评论(0编辑  收藏  举报