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函数!!

原文地址:https://www.cnblogs.com/shihuajie/p/2624592.html