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;
}
posted @ 2010-07-10 15:47  open source  阅读(511)  评论(0编辑  收藏  举报