1003 Problem D
An entropy encoder is a data encoding method that achieves lossless data compression by encoding a message with “wasted” or “extra” information removed.
题意:对于一串字符,让使用频率高的二进制表示尽可能小,最终使得表示这串字符的二进制数最少。
思路:对于英文字母的编码就是求最优树,哈夫曼树每次让权值最小的树结合,得到新的节点,再利用新得到的权值,去计算下一个最小权值,最终让所有权值结合成一棵树,即得到最优树,以此来编码。
感想:权值的记录,以及左右兄弟的组合是问题关键,处理好此处,问题自然可解。
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
struct str{
int l,r,c;
}tree[64];
int f[60];
int k;
string s;
void hefuman(int n,int p){
if(f[n]==0) return ;
if(n<=26) k+=f[n]*p;
else{
hefuman(tree[n].l,++p);
hefuman(tree[n].r,p);
}
}
int main(){
int i,j,left,right;
while(cin>>s){
if(s=="END") break;
int len=s.length();
for(i=0;i<=60;i++) tree[i].c=-1;
memset(f,0,sizeof(f));
for(i=0;i<len;i++){ //统计字符个数
if(s[i]=='_') f[26]++;
else f[s[i]-'A']++;
}
int node=26;
while(1){
int min=1000;
for(i=0;i<=node;i++){
if(tree[i].c==-1){
if(min>f[i]&&f[i]){
min=f[i];
left=i;
}
}
}
min=1000;
for(j=0;j<=node;j++){
if(tree[j].c==-1){
if(min>f[j]&&j!=left&&f[j]){
min=f[j];
right=j;
}
}
}
if(min==1000) break;
f[++node]=f[left]+f[right];
tree[node].l=left;
tree[node].r=right;
tree[node].c=-1;
tree[left].c=node;
tree[right].c=node;
}
k=0;
if(node==26) k=len;
else hefuman(node,0);
len*=8;
printf("%d %d %.1f\n",len,k,len*1.0/k);
}
return 0;
}