hdu1053 Entropy

 1 #include<iostream>

 2 #include<iomanip>

 3 #define N 27

 4 using namespace std;

 5 int cmp(const void *a,const void *b)

 6 {

 7     return *(int *)b-*(int *)a;   //从大到小排序,方便对最小次小值的 操作 

 8 }

 9 int main()

10 {

11     string s;

12     int num[27],a[27];

13     int i,j,wpl,len;

14     while(cin>>s,s!="END"){

15         memset(num,0,sizeof(num));

16         for(i=0;s[i];++i){

17             if(s[i]=='_') num[26]++;

18             else num[s[i]-'A']++;

19         }

20         len=i;

21         qsort(num,N,sizeof(int),cmp);

22         for(i=0;i<N&&num[i];++i)

23             a[i]=num[i];

24         for(wpl=0,j=i-1;j>0;--j){  //核心代码! 每次把最小的那个加到次小的上面,然后把加后的值计入到wpl中,再排序! 

25             a[j-1]+=a[j];

26             wpl+=a[j-1];

27             qsort(a,j,sizeof(int),cmp);

28         }

29         if(i==1) wpl=len;   //注意,只有一种字母的时候,是个特殊情况 

30         cout<<8*len<<" "<<wpl<<" "<<fixed<<setprecision(1)<<8.0*len/wpl<<endl;

31     }

32     return 0;

33 }

这道题是周赛的时候看到的,当时虽然懂得哈弗曼编码的思想与算法,觉得必须建一棵树,然后遍历所有叶子节点,只要求出各个叶子的深度,然后求wpl就容易了,但其中过程有些复杂,太耗时间了,所以我放弃了,但现在反过来再看它,其实没必要建一棵树,直接把每次新生成节点的权都加起来就行了,这样深度为n的叶子节点自然就加了n次啦!在本题中我用的是快速排序,其实快速排序在这题中有点不合适,快速排序属于交换类排序,交换类排序要想得到最小次小的数,需要全部排序,而本题恰恰只需要得到最小次小的就行了,所以本题用选择类排序最好了,如:简单选择排序,堆排序等!我是为了使代码精简所以使用了系统自带的qsort函数!!

你可能感兴趣的:(HDU)