#include<iostream> / * HDU 2527 裸的哈夫曼樹 * /#include<string>#include<map>using namespace std;#define manx 100#define inf 9999999;map<char,int>mp;struct node{ int weight; int parent; int lch; int rch; string code; /// 哈夫曼碼值 string val; /// 字元 };void init(node *hfnode,int n){ /// 初始化 for(int i=0;i<(n<<1)-1;i++){ hfnode[i].weight=0; hfnode[i].parent=-1; hfnode[i].lch = hfnode[i].rch = -1; hfnode[i].code.clear(); hfnode[i].val.clear(); }}void make_tree(node *hfnode,int n){ /// 建哈夫曼樹 int m1, m2, x1, x2; for(int i=1;i<n;i++){ m1 = m2 = inf; /// 記錄最小和其次小的值 x1 = x2 = 0; /// 記錄最小和其次的值的位置 for(int j=1;j<n+i;j++){ /// 查詢,找到最小和其次小的位置 if(hfnode[j].weight < m1 && hfnode[j].parent < 0){ m2 = m1; x2 = x1; m1 = hfnode[j].weight; x1 = j; } else if(hfnode[j].weight < m2 && hfnode[j].parent <0 ){ m2 = hfnode[j].weight; x2 = j; } } hfnode[x1].parent = n+i; /// 然後父親節點進行更新 hfnode[x2].parent = n+i; hfnode[n+i].weight = hfnode[x1].weight + hfnode[x2].weight; /// 權值更新 hfnode[n+i].lch = x1; /// 左右孩子進行記錄 hfnode[n+i].rch = x2; }}void tree_code(node *hfnode, int m, int n ){ /// 採用遞迴的形式建立哈夫曼編碼值 if( m<=n ) return ; if(hfnode[m].lch > 0) { hfnode[ hfnode[m].lch ].code = "0"; } if(hfnode[m].rch > 0) { hfnode[ hfnode[m].rch ].code = "1"; } tree_code( hfnode, hfnode[m].lch, n ); tree_code( hfnode, hfnode[m].rch, n ); }string e,hh; /// hh 表示哈夫曼編碼,它的長度也表示深度 /// e 表示目標 值 void tree_dfs( node *hfnode,int m,int n,string s,int &flag ){ /// 深搜 if( hfnode[m].val == e ){ /// 查詢 flag=1, hh=s; return ; } if(flag || m <= n) return ; if(hfnode[m].lch > 0) { tree_dfs(hfnode,hfnode[m].lch, n, s+hfnode[ hfnode[m].lch ].code, flag); } if(hfnode[m].rch > 0) { tree_dfs(hfnode,hfnode[m].rch, n, s+hfnode[ hfnode[m].rch ].code, flag); }}int main(){ node hfnode[manx*4]; string str; int n1,t; cin>>t; while(t--){ int ans1; cin>>ans1>>str; mp.clear(); n1 = str.size(); init(hfnode,manx); int n=0,ans=1; for(int i=0;i<n1;i++) mp[str[i]]++; for(int i=0;i<n1;i++){ if(mp[str[i]]){ hfnode[++n].weight = mp[str[i]]; hfnode[n].val = str[i]; mp[str[i]]=0; } } int flag=0,sum=0,du=0; if(n==1) { sum = hfnode[1].weight; if(sum<=ans1) printf("yes\n"); else printf("no\n"); continue; } make_tree(hfnode,n); tree_code( hfnode,(n<<1)-1 ,n ); string hfcode; for(int i=1;i<=n;i++){ flag = 0; hfcode.clear(); e.clear(); hh.clear(); e = hfnode[i].val; tree_dfs( hfnode, (n<<1)-1, n, hfcode, flag ); sum += (hh.size())*(hfnode[i].weight); } if(sum<=ans1) printf("yes\n"); else printf("no\n"); }}
其實挺簡單的,前幾天自己寫的課設就是哈夫曼樹..
題意:要你求 8*str.size() , sum(最優權值), 8*str.size() / (sum*1.0)
代碼:
/*因為總計就是27個字元(狀態),所以深搜是完全沒有壓力的 */ #include<iostream>#include<string>#include<map>using namespace std;#define manx 100#define inf 9999999;map<char,int>mp;struct node{ int weight; int parent; int lch; int rch; string code; /// 哈夫曼碼值 string val; /// 字元 };void init(node *hfnode,int n){ /// 初始化 for(int i=0;i<(n<<1)-1;i++){ hfnode[i].weight=0; hfnode[i].parent=-1; hfnode[i].lch = hfnode[i].rch = -1; hfnode[i].code.clear(); hfnode[i].val.clear(); }}void make_tree(node *hfnode,int n){ /// 建哈夫曼樹 int m1, m2, x1, x2; for(int i=1;i<n;i++){ m1 = m2 = inf; /// 記錄最小和其次小的值 x1 = x2 = 0; /// 記錄最小和其次的值的位置 for(int j=1;j<n+i;j++){ /// 查詢,找到最小和其次小的位置 if(hfnode[j].weight < m1 && hfnode[j].parent < 0){ m2 = m1; x2 = x1; m1 = hfnode[j].weight; x1 = j; } else if(hfnode[j].weight < m2 && hfnode[j].parent <0 ){ m2 = hfnode[j].weight; x2 = j; } } hfnode[x1].parent = n+i; /// 然後父親節點進行更新 hfnode[x2].parent = n+i; hfnode[n+i].weight = hfnode[x1].weight + hfnode[x2].weight; /// 權值更新 hfnode[n+i].lch = x1; /// 左右孩子進行記錄 hfnode[n+i].rch = x2; }}void tree_code(node *hfnode, int m, int n ){ /// 採用遞迴的形式建立哈夫曼編碼值 if( m<=n ) return ; if(hfnode[m].lch > 0) { hfnode[ hfnode[m].lch ].code = "0"; } if(hfnode[m].rch > 0) { hfnode[ hfnode[m].rch ].code = "1"; } tree_code( hfnode, hfnode[m].lch, n ); tree_code( hfnode, hfnode[m].rch, n ); }string e,hh; /// hh表示哈夫曼編碼,它的長度也算是深度 /// e 表示目標值 void tree_dfs( node *hfnode,int m,int n,string s,int &flag ){ /// 深搜 if( hfnode[m].val == e ){ /// 當查詢到時 flag=1, hh=s; return ; } if(flag || m <= n) return ; /// 兩個成立的條件 if(hfnode[m].lch > 0) { tree_dfs(hfnode,hfnode[m].lch, n, s+hfnode[ hfnode[m].lch ].code, flag); } if(hfnode[m].rch > 0) { tree_dfs(hfnode,hfnode[m].rch, n, s+hfnode[ hfnode[m].rch ].code, flag); }}int main(){ node hfnode[manx*4]; string str; int n1; while(getline(cin,str)){ mp.clear(); if(str=="END") break; n1 = str.size(); init(hfnode,manx); int n=0,ans=1; for(int i=0;i<n1;i++) mp[str[i]]++; /// map 統計單個字元出現的次數 for(int i=0;i<n1;i++){ if(mp[str[i]]){ hfnode[++n].weight = mp[str[i]]; hfnode[n].val = str[i]; mp[str[i]]=0; } } if(n==1) { //// 要注意 cout<<8*str.size()<<" "<<hfnode[n].weight<<" "; printf("%.1lf\n",(8*str.size())/(hfnode[n].weight*1.0)); continue; } make_tree(hfnode,n); tree_code( hfnode,(n<<1)-1 ,n ); string hfcode; int flag=0,sum=0,du=0; for(int i=1;i<=n;i++){ flag = 0; hfcode.clear(); e = hfnode[i].val; tree_dfs( hfnode, (n<<1)-1, n, hfcode, flag ); sum += (hh.size())*(hfnode[i].weight); } cout<<8*str.size()<<" "<<sum<<" "; printf("%.1lf\n",(8*str.size())/(sum*1.0)); }}/*THE_CAT_IN_THE_HATAAAAABCD*/