本题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2527
此题考查的是哈夫曼树,构造哈夫曼树并计算出最小编码数即可。
做此题的过程中,提交之后竟然TLE,很是郁闷,找了几遍,还是没找出错误,可以肯定算法是不会错的,这方面不会超时,当测试只有一个字符的时候,发现问题了,出现了死循环,因为当只有1个或一种相同的字符的时候,并没有进行构造哈弗曼数的过程,因此在下面的找最小编码数的时候,出现了死循环,这个地方需要特殊计算最小编码数。改过之后,立刻就AC了,真是感慨,不过还挺满意的,自己构造出了哈夫曼树,继续加油!\(^o^)/~
AC代码如下:
#include<iostream> using namespace std; #include<string.h> struct node { int r,l,p,data; }ha[100]; char s[100000]; int main() { //freopen("d:\\1.txt","r",stdin); int n,a[27],b[27],c[27]; cin>>n; while(n--) { int m1,h,s1=0; int i,j,k=0; cin>>m1; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); scanf("%s",s); int l=strlen(s); for(i=0;i<l;i++) { int m=s[i]-96; a[m]++; } for(i=1;i<=26;i++) { if(a[i]) b[++k]=a[i]; } if(k!=1)//特别注意要考虑k=1的情况,因为没有进行构成哈夫曼树的操作,所以将会在下面出现死循环 { //构造哈夫曼树 memset(ha,0,sizeof(ha)); for(i=1;i<=k;i++) ha[i].data=b[i]; for(i=1;i<k;i++)//共有k-1个结点需要补充 { int max=10000000; int m1,m2,x1,x2; m1=max;//m2存上一个m1的值,m1存最新的值,x2存上一个x1的值,x1存最新的值 m2=max;//m1,m2存结点的权值,x1,x2分别存结点的左右孩子的位置 x1=0; x2=0; for(j=1;j<k+i;j++) { if(ha[j].data<m1&&ha[j].p==0) { m2=m1; m1=ha[j].data; x2=x1; x1=j; } else if(ha[j].data<m2&&ha[j].p==0) { m2=ha[j].data; x2=j; } } ha[k+i].l=x1; ha[k+i].r=x2; ha[x1].p=k+i; ha[x2].p=k+i; ha[k+i].data=ha[x1].data+ha[x2].data; } //测试输出树 /*for(i=1;i<2*k;i++) { cout<<i<<' '<<ha[i].l<<' '<<ha[i].data<<' '<<ha[i].r<<' '<<ha[i].p<<endl; }*/ //求最小编码数 for(i=1;i<=k;i++) { j=i; for(;;) { h=ha[j].p; j=h; c[i]++; if(h==2*k-1)break;//若不讨论 将会在此死循环 因为h会恒等于0 } s1+=b[i]*c[i]; } } else s1=b[1]*1; //cout<<"s1="<<s1<<endl; if(s1<=m1)cout<<"yes"<<endl; else cout<<"no"<<endl; } return 0; }