问题描述
试题编号: | 201612-4 |
试题名称: | 压缩编码 |
时间限制: | 3.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 给定一段文字,已知单词a1, a2, …, an出现的频率分别t1, t2, …, tn。可以用01串给这些单词编码,即将每个单词与一个01串对应,使得任何一个单词的编码(对应的01串)不是另一个单词编码的前缀,这种编码称为前缀码。 输入格式 输入的第一行包含一个整数n,表示单词的数量。 输出格式 输出一个整数,表示文字经过编码后的长度L的最小值。 样例输入 5 样例输出 34 样例说明 这个样例就是问题描述中的例子。如果你得到了35,说明你算得有问题,请自行检查自己的算法而不要怀疑是样例输出写错了。 评测用例规模与约定 对于30%的评测用例,1 ≤ n ≤ 10,1 ≤ ti ≤ 20; |
参考代码(平行四边形优化-百度百科)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <queue>
using namespace std;
int n;
int dp[1005][1005];
int s[1005][1005];
int sum[1005];
int main(){
cin >> n;
for(int i=0;i<1005;i++){
for(int j=0;j<1005;j++){
dp[i][j]=0x7f7f7f7f;
}
}
sum[0]=0;
for(int i=1;i<=n;i++){
int a;
cin >> a;
sum[i]=sum[i-1]+a;
dp[i][i]=0;
s[i][i]=i;
}
for(int L=2;L<=n;L++){
for(int i=1;i+L-1<=n;i++){
int j=i+L-1;
for(int k=s[i][j-1];k<=s[i+1][j];k++){
int val=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
if(dp[i][j]>val){
dp[i][j]=val;
s[i][j]=k;
}
}
}
}
cout << dp[1][n] << endl;
return 0;
}