哈夫曼编码问题

Description

给定一个数字N,代表有N种不同的字符,已知每种字符的出现次数,现在要求你设计一种编码,使得任意一个编码都不是另外一个编码的前缀,并且使得这些字符经过编码压缩之后的总长度最小; 

Input

一个数字N 代表有多少种不同的字符(0<=N<=1000)N个数字  每个数字代表一种字符的出现次数

Output

一个数字,代表总的编码长度

Sample Input

5
1
2
3
4
5

3
3
8
8

Sample Output

33
30

正常版

#include<bits/stdc++.h>
using namespace std;
bool bj[2001];
struct jg{
    int l,r,q;
};
struct nsj
{
    int n1,n2;
};
int data[2001],cd[2001];
jg shu[2001];
void dfs(int x,int y);
nsj zhapy(int x);
int main()
{
    int n,i,cnt;
    nsj n12;
    while(cin>>n)
    {
        memset(cd,0,sizeof(cd));
        memset(shu,0,sizeof(shu));
        for(i=1;i<=n;i++)
        {
            cin>>data[i];
        }
        for(i=1;i<=n;i++)
        {
            bj[i]=true;
            bj[i+n]=false;
        }
        cnt=n;
        while(cnt<2*n-1)
        {
            n12=zhapy(cnt);
            bj[n12.n1]=bj[n12.n2]=false;
            cnt++;
            bj[cnt]=true;
            shu[cnt].l=n12.n1;
            shu[cnt].r=n12.n2;
            shu[cnt].q=data[n12.n1]+data[n12.n2];
            data[cnt]=data[n12.n1]+data[n12.n2];
        }
        dfs(2*n-1,0);
        int ans=0;
        for(i=1;i<=n;i++)
        {
            ans+=cd[i]*data[i];
        }
        cout<<ans<<endl;
    }
    return 0;
}
nsj zhapy(int x)
{
    nsj cnt;
    int x1,x2,i;
    x1=999999999;
    x2=999999999;
    cnt.n1=1;
    cnt.n2=1;
    for(i=1;i<=x;i++)
    {
        if(bj[i])
        {
            if(data[i]<x1)
        {
            x2=x1;
            cnt.n2=cnt.n1;
            x1=data[i];
            cnt.n1=i;
        }
        else if(data[i]<x2)
        {
            cnt.n2=i;
            x2=data[i];
        }
        }

    }
    return cnt;
}
void dfs(int x,int y)
{
    int l,r;
    l=shu[x].l;
    if(l!=0)
    {
        dfs(l,y+1);
        r=shu[x].r;
        dfs(r,y+1);
    }
    else
    {
        cd[x]=y;
    }
}

变态版:

#include<bits/stdc++.h>
using namespace std;bool bj[2001];struct jg{int l,r,q;};struct nsj{int n1,n2;};int data[2001],cd[2001];jg shu[2001];void dfs(int x,int y);nsj zhapy(int x);int main(){int n,i,cnt;nsj n12;while(cin>>n){memset(cd,0,sizeof(cd));memset(shu,0,sizeof(shu));for(i=1;i<=n;i++){cin>>data[i];}for(i=1;i<=n;i++){bj[i]=true;bj[i+n]=false;}cnt=n;while(cnt<2*n-1){n12=zhapy(cnt);bj[n12.n1]=bj[n12.n2]=false;cnt++;bj[cnt]=true;shu[cnt].l=n12.n1;shu[cnt].r=n12.n2;shu[cnt].q=data[n12.n1]+data[n12.n2];data[cnt]=data[n12.n1]+data[n12.n2];}dfs(2*n-1,0);int ans=0;for(i=1;i<=n;i++){ans+=cd[i]*data[i];}cout<<ans<<endl;}return 0;}nsj zhapy(int x){nsj cnt;int x1,x2,i;x1=999999999;x2=999999999;cnt.n1=1;cnt.n2=1;for(i=1;i<=x;i++){if(bj[i]){if(data[i]<x1){x2=x1;cnt.n2=cnt.n1;x1=data[i];cnt.n1=i;}else if(data[i]<x2){cnt.n2=i;x2=data[i];}}}return cnt;}void dfs(int x,int y){int l,r;l=shu[x].l;if(l!=0){dfs(l,y+1);r=shu[x].r;dfs(r,y+1);}else{cd[x]=y;}}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值