hdu2527 Safe Or Unsafe 哈夫曼树

哈夫曼树之杭电2527    2012-5-23 22:09阅读(0)

Safe Or Unsafe

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 660    Accepted Submission(s): 220


Problem Description
Javac++ 一天在看计算机的书籍的时候,看到了一个有趣的东西!每一串字符都可以被编码成一些数字来储存信息,但是不同的编码方式得到的储存空间是不一样的!并且当储存空间大于一定的值的时候是不安全的!所以Javac++ 就想是否有一种方式是可以得到字符编码最小的空间值!显然这是可以的,因为书上有这一块内容--哈夫曼编码(Huffman Coding);一个字母的权值等于该字母在字符串中出现的频率。所以Javac++ 想让你帮忙,给你安全数值和一串字符串,并让你判断这个字符串是否是安全的?
 

Input
输入有多组case,首先是一个数字n表示有n组数据,然后每一组数据是有一个数值m(integer),和一串字符串没有空格只有包含小写字母组成!
 

Output
如果字符串的编码值小于等于给定的值则输出yes,否则输出no。
 

Sample Input
   
   
   
   
212helloworld66ithinkyoucandoit
 

Sample Output
   
   
   
   
noyes
 

Source
HDU 2008-10 Programming Contest
 

Recommend
gaojie


#include<stdio.h>
#include<string.h>
#define len 100000
struct haha
{
    int start;
    int l[len];
    int weight;
}code[100],cd;
struct xixi
{
    int weight;
    int parent;
    int l_child;
    int r_child;
}tree[100];
int a[300];
int main()
{
    char c[100000];
    int n,k,t,i,j,m,d,m1,m2,x1,x2,pare,child,ans,temp,cnt;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        n=0;
        scanf("%d",&k);
        getchar();
        gets(c);
        d=strlen(c);
        memset(a,0,sizeof(a));
        for(i=0;i<d;i++)
            a[c[i]]++;
        j=0;
        for(i=90;i<130;i++)
            if(a[i]!=0)
            {
                tree[n].weight=a[i];
                tree[n].l_child=-1;
                tree[n].r_child=-1;
                tree[n].parent=-1;
                n++;                               
            }
            m=2*n-1;
            for(i=n;i<m;i++)
            {
                tree[i].l_child=-1;
                tree[i].r_child=-1;
                tree[i].parent=-1;
                tree[i].weight=0;
            }
            for(i=0;i<n-1;i++)
            {
                m1=m2=1000000000;//记录权值
                x1=x2=0;//记录 节点所在位置
                for(j=0;j<n+i;j++)
                {
                    if(tree[j].weight<m1&&tree[j].parent==-1)
                    {
                        m2=m1;
                        x2=x1;
                        m1=tree[j].weight;
                        x1=j;
                    }
                    else if(tree[j].weight<m2&&tree[j].parent==-1)
                    {
                        m2=tree[j].weight;
                        x2=j;
                    }
                }
                tree[n+i].weight=tree[x1].weight+tree[x2].weight;
                tree[x1].parent=n+i;
                tree[x2].parent=n+i;
                tree[n+i].l_child=x1;
                tree[n+i].r_child=x2;       
            }
            for(i=0;i<n;i++)
            {
                cd.start=n-1;
                child=i;
                pare=tree[child].parent;
                while(pare!=-1)
                {
                    if(tree[pare].l_child==child)
                        cd.l[cd.start]=0;
                    else cd.l[cd.start]=1;
                    cd.start--;
                    child=pare;
                    pare=tree[child].parent;
                }
                for(j=cd.start+1;j<n;j++)
                {
                    code[i].l[j]=cd.l[j];
                }
                code[i].start=cd.start+1; 
                code[i].weight=tree[i].weight;
                //   printf("code[i]=%d d=%d\n",code[i].start,n-code[i].start);
            }
        /*        for(i=0;i<n;i++)
                {
                  ans=ans+(n-code[i].start)*tree[i].weight;//这样是错误的 因为当长度长的时候权值却可能很大
            //      printf("changdu=%d\n",n-code[i].start);
                 }
             printf("ans=%d\n",ans);
             */
            for(i=0;i<n;i++)
            {
                temp=i;cnt=0;
                while(tree[temp].parent!=-1)
                {
                    /*当n为1的时候只有一个节点无法组成树 所以父亲节点为-1
                造成了cnt=0  即ans也等于0  如果有数据  10 10  dddddddddddddddddddddd就不对了
                要处理下特殊情况才行
                    */
                    temp=tree[temp].parent;
                    cnt++;
                }
                ans=ans+cnt*tree[i].weight;
            }
            if(n==1) ans=tree[0].weight;// 要特别注意这个地方 因为当n等于1的时候就一个编码为0
              if(ans<=k) printf("yes\n");
                 else printf("no\n");
    }
    return 0;
}


你可能感兴趣的:(struct,tree,Integer,ini,input,output)