http://poj.org/problem?id=1521
Entropy
Time Limit: 1000MS Memory Limit: 10000K
P.S. 原题真长
题目大意:
给定一些只包含 大写字母 和 下划线 的字符串,求利用huffman编码的原理,存储每个字符串需要的最少bit数。
Input
The input file will contain a list of text strings, one per line. The text strings will consist only of uppercase alphanumeric characters and underscores (which are used in place of spaces). The end of the input will be signalled by a line containing only the word “END” as the text string. This line should not be processed.
Output
For each text string in the input, output the length in bits of the 8-bit ASCII encoding, the length in bits of an optimal prefix-free variable-length encoding, and the compression ratio accurate to one decimal point.
Sample Input
AAAAABCD THE_CAT_IN_THE_HAT END
Sample Output
64 13 4.9 144 51 2.8
(每个字符8bit需要的空间、按huffman编码需要的空间、二者的比值)
解法:
裸的huffman树。把各个字母出现的次数放入优先队列,每次取出其中两个加起来,形成新的结点,再放入队列即可。
在这里学习了一下如何在优先队列里放指针。
200K 0MS 语言选C++ ,选G++会CE
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
const int inf=105;
class cmp;//由于cmp和C类互相调用,所以在此提前声明
class C{public:
C *ls,*rs;
int t;
C(){ls=rs=NULL;t=0;}
friend cmp;
};
class cmp{public:
bool operator () (C*a,C*b){return a->t > b->t;}//重载小于号时,参数不能是两个指针
};
int dfs(C* rt,int dep){
if (!rt->ls && !rt->rs) return rt->t*dep;
int tot=0;
if (rt->ls) tot+=dfs(rt->ls,dep+1);
if (rt->rs) tot+=dfs(rt->rs,dep+1);
return tot;
}
int main(){
string s;
while(cin>>s){
if (s=="END") return 0;
int len=s.length();
double store=0;
priority_queue<C*,vector<C*>,cmp> q;
C* c[inf];for (int i=0;i<inf;i++) c[i]=new C;
for (int i=0;i<len;i++) c[s[i]]->t++;
int tot=0;
for (int i=0;i<inf;i++)
if (c[i]->t) q.push(c[i]),tot++;
if (tot==1) store=len; //只有一种字母时,队列中只有一个元素,不能建树
else{
C* root;
while(1){
C* ls=q.top();q.pop();
C* rs=q.top();q.pop();
C* rt=new C;
rt->ls=ls,rt->rs=rs;
rt->t=ls->t+rs->t;
if (q.empty()) {root=rt;break;}
q.push(rt);
}
store=dfs(root,0);
}
printf("%d %.0llf %.1llf\n",len*8,store,len*8/store);
for (int i=0;i<inf;i++) delete c[i];
}
return 0;
}