Safe Or Unsafe(hdu2527)哈弗曼VS優先佇列

尋找&星空の孩子發表於2013-08-22

 

Safe Or Unsafe

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

Problem Description
Javac++ 一天在看計算機的書籍的時候,看到了一個有趣的東西!每一串字元都可以被編碼成一些數字來儲存資訊,但是不同的編碼方式得到的儲存空間是不一樣的!並且當儲存空間大於一定的值的時候是不安全的!所以Javac++ 就想是否有一種方式是可以得到字元編碼最小的空間值!顯然這是可以的,因為書上有這一塊內容--哈夫曼編碼(Huffman Coding);一個字母的權值等於該字母在字串中出現的頻率。所以Javac++ 想讓你幫忙,給你安全數值和一串字串,並讓你判斷這個字串是否是安全的?
 
Input
輸入有多組case,首先是一個數字n表示有n組資料,然後每一組資料是有一個數值m(integer),和一串字串沒有空格只有包含小寫字母組成!
 
Output
如果字串的編碼值小於等於給定的值則輸出yes,否則輸出no。
 
Sample Input
2
12
helloworld
66
ithinkyoucandoit
 
Sample Output
no
yes
 
這幾天在忙著看二叉樹,,,╮(╯▽╰)╭   理解能力有待加強,,,
 
這道題的意思是 m與哈弗曼樹除了葉子的權值(非葉子節點的權值之和);用優先佇列模擬哈弗曼樹;

/* 題意:就是給你一個字串如:12     helloworld統計出其中d:1個,e:1個,h:1個,l:3個,o:2個,r:1個,w:1個,

然後用一個陣列儲存起來a[7]={1,1,1,1,1,2,3};然後就是用哈夫曼樹的思想求出新建的非葉子節點的權值之和:sum與12相比較

如果sum小於等於12的話就輸出yes否則輸出no,此案例求出的sum=27;所以輸出no。

思路:按照建立哈夫曼樹的思路每次求出兩個的權值用min1儲存最小的,min2儲存次小的,

然後(min1+min2)加入其中,但是min1和min2需要踢出去,此題我用優先佇列做的,就是

每次彈出最小的(min1)和次小的(min2),然後把(min1+min2)壓入佇列中。//題中a=min1;b=min2;

但是有一組很坑爹的測試資料,開始的時候一直錯,5 aaaaa 輸出的是yes,5 aaaaaa輸出的是no*/

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;

priority_queue<int, vector<int>, greater<int> >Q;//從小到大,優先佇列

char str[10001];
int huf[26];
int n;

void solve()
{
    int ans=0;
    int a,b;
    while(Q.size()!=1)
    {
        a=Q.top();//優先佇列區最小的數(認為已經排好順序了)
        Q.pop();
        b=Q.top();
        Q.pop();
        Q.push(a+b);//把新的根入隊;
        ans+=(a+b);//本題要求的權值;
    }
    printf(ans<=n?"yes\n":"no\n");
}

int main()
{
    int T,i,len;
    scanf("%d",&T);
    while(T--)
    {
        while(!Q.empty())//保證佇列為空
            Q.pop();
        memset(huf,0,sizeof(huf));
        scanf("%d",&n);
        scanf("%s",str);
        len=strlen(str);
        for(i=0;i<len;i++)
        {
            huf[str[i]-'a']++;//統計各個字母的個數
        }
        for(i=0;i<26;i++)
            if(huf[i])//如果有字母就入隊
                Q.push(huf[i]);
        if(Q.size()==1)//沒有子葉的情況
        {
            int m=Q.top();
            Q.pop();
            printf(m<=n?"yes\n":"no\n");
        }
        else
            solve();

    }
    return 0;
}

 

 

 

 

       我的一道樹的題目,紀念一下我的入門,,,哈哈

 

 

下面是用哈弗曼樹寫的,有點麻煩;感覺還是優先佇列模擬的好,不過也可以參考一下哈

 

 

 

#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
struct node
{
  int weight;
  int parent,left,right;
};
char a[100001];
int huf(int str[],int size)
{
   int i,lenth=2*size,min1,min2,x,y,sum=0,j;
   struct node *hf;
   hf=(struct node *)malloc(lenth*sizeof(struct node));//開創
   for(i=size;i<lenth;i++)
   {
      hf[i].weight=str[i-size];
      hf[i].parent=hf[i].left=hf[i].right=0;
   }
   for(i=size-1;i>0;i--)
   {
       min1=min2=10000000;
       x=y=0;
       for(j=i+1;j<lenth;j++)
       {
           if(min1>hf[j].weight&&hf[j].parent==0)
           {
               min2=min1;
               y=x;
               min1=hf[j].weight;
               x=j;
           }
           else if(min2>hf[j].weight&&hf[j].parent==0)
           {
               y=j;
               min2=hf[j].weight;
           }
       }
       hf[i].weight=min1+min2;
       sum=sum+hf[i].weight;
       hf[i].parent=0;
       if(x>y)
           swap(x,y);
       hf[i].left=y;
       hf[i].right=x;
       hf[x].parent=i;
       hf[y].parent=i;
   }
   return sum;
}
int main()
{
    int T,n,i,j,len,num[26],b[26];
    while(scanf("%d",&T)!=EOF)
    {
        while(T--)
        {
           len=0;
           memset(b,0,sizeof(b));
           scanf("%d",&n);
           getchar();
           scanf("%s",a);
           for(i=0;a[i]!='\0';i++)
               b[a[i]-'a']++;//把字母個數存入陣列
           for(i=0;i<26;i++)
               if(b[i]!=0)
                   num[len++]=b[i];//除去空字母
               if(len==1)
               {
                   if(num[0]<=n)
                     printf("yes\n");
                   else
                     printf("no\n");
               } 
               else
               {
                   if(huf(num,len)<=n)
                      printf("yes\n");
                   else
                      printf("no\n");
               }
        }
    }
    return 0;
}

 

 

 

相關文章