#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_HAT
AAAAABCD
*/