优先队列实现哈夫曼树——中堂系的困难任务

本文介绍了一道与哈夫曼树相关的DP题目,通过分析给出的公式与哈夫曼树DP公式之间的联系,利用优先队列实现了哈夫曼树的构建过程,最终求得最小带权路径和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

题目链接CDOJ中堂系的困难任务

题目描述

 

 

 

 

 

 

 

 

 

Sample input and output

Sample InputSample Output
3
3
1 1 1
5
28 26 25 24 1
10
996 901 413 331 259 241 226 209 139 49
5
233
11037

 

按照题目给的公式稍微推一下发现f ( i,  j) = min(f (i -1 ,j+1 ) , f ( i, j/2 ) +b[ i ] ) 这个公式与哈夫曼树的dp式有些相似,

哈夫曼树的dp推导

先对元素从大到小排序。 
设f( i , j )表示现在已经做了前i个元素,还空出来j个叶子节点的最小代价。 
第一种转移显然,就是把第i+1个元素放到一个叶子节点上,f ( i+1,j−1 )=f (i , j )。 
第二种转移就是把当前剩下的叶子节点都再生成出两个节点来,代价是把当前的剩下元素全部加深了一层,所以

f( i,2∗j )=f( i,j )+b[ i+1 ]。    Ans=min(fn,k)

所以题目的公式就是哈夫曼树的推导式;f (n,1) 就是最小带权路径和;

然后看样例发现恰好是这样,逃....ε=ε=ε=┏(゜ロ゜;)┛

所以直接用优先队列模拟堆实现,类比合并果子那个题

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=1e5+7;
int t;
int a[maxn];
int b[maxn];
int n;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        priority_queue<long long,vector<long long > ,greater<long long > > q;
        long long cnt=0;
        for(int i=1;i<=n;i++)
            {
                cin>>a[i];
                q.push(a[i]);
                cnt+=a[i];
            }

        long long ans=0;
        while(q.size()>1)
        {
            long long f1=q.top();
            q.pop();
            long long f2=q.top();
            q.pop();
            ans+=f1+f2;
            q.push(f1+f2);
        }
        cout<<ans<<endl;

        //    cout<<ans-cnt<<endl;



    }
    return 0;
}

 

 

哈夫曼树知识补充:

哈夫曼树

给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

对于一颗哈夫曼树,我们把所有节点排序,权值大的必定层数较低,f[i][j]代表已经放了i-1个叶子节点,正准备放置Ai,该层还有j个空节点我们可以选择在空节点上放一个叶子节点,从而转移到状态f[i+1][j-1],或者选择移动到下一层,即转移到f[i][j*2],该树权值增大量剩下节点的总权值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值