hdoj1053(Huffman)
Entropy
本来作过的,今天又看了下发现不用建Huffman树的,又做了一遍,先是用堆,出现n多错误,改用优先队列,又忘记将freopen("input","r",stdin)注释掉,杭电上显示超时!折腾了三个多小时,郁闷啊!
/***************************************************************\
*Author: 小呼
*Created Time: Sat 10 Jul 2010 03:21:54 PM CST
*File Name: b.cpp
*Description:Huffman编码问题。但并不需要构造Huffman树,因为并没有
*要求给出编码。只是要求编码的总长度,也就是求Huffman树的带权路径
*长度,而这个值等于树上各非终端结点的和(可以验证),于是只需要
*先求出出现的各种字符的出现次数,将两个最小的求和(这个和在Huffman
*树中是一个非终端结点,标记答案的变量res将它加一次),将它放入队列
*中,再求两个最小的数之和,再用res加一次,再将和放入队列中,直到
*队列中只有一个数为止。应当单独考虑下字符串中只出现一个字符的情况
*至于队列的实现可以用堆实现,也可以用优先队列,在时间复杂度上两者是
*相同的。
\***************************************************************/
//*========================*Head File*========================*\\
#include<iostream>
#include<queue>
#include<stdio.h>
#include<stdlib.h>
/*----------------------*Global Variable*----------------------*/
struct mycmp{//重载优先队列的比较,优先队列默认是升序的
bool operator()(const int &a, const int &b){
return a>b;
}
};
char str[1000];
//*=======================*Main Program*=======================*//
using namespace std;
int main(){
priority_queue<int,vector<int>,mycmp> pq;
// freopen("input","r",stdin);
while(true){
gets(str);
if(str[0]=='E'&&str[1]=='N'&&str[2]=='D'&&str[3]==0)
return 0;
int len=0;//字符串长度
while(str[len])
len++;
for(int i=0;i<len;++i){
if(str[i]=='#') //用‘#’作为已经计算过的标志,
//因为它不会在字符串中出现
continue;
int sum=1;
for(int j=i+1;j<len;++j){
if(str[j]==str[i]){
sum++;
str[j]='#';
}
}
pq.push(sum);
}
int res=0;//Huffman树的带权路径长度,即总编码的长度
while(!pq.empty()){
int a,b;
a=pq.top();
pq.pop();
if(pq.empty())break;//pq中只有一个数时跳出
b=pq.top();
pq.pop();
res+=a+b;
pq.push(a+b);
}
if(res==0)//res=0说明字符串中只有一种字符,要特殊考虑
res=len;
printf("%d %d %.1lf\n",8*len,res,8.0*len/res);
}
return 0;
}