洛谷2168荷马史诗
#include
#include
#include
#include
#include
using namespace std;
typedef pair
priority_queue, greater> que;
int n, k, Num = 0;
long long Length = 0, Ans = 0, x;
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> x;
que.push(aii(x,1));//节点的权值,层数//初始时候每个节点都是第一层
}
if ((n - 1) % (k - 1) != 0)//
Num = k - 1 - (n - 1) % (k - 1);//当结点不够时,插入值为零的虚节点,不然算出来可能不是最优解
for (int i = 1; i <= Num; i++)//插入虚节点,其实就是因为完全二叉树的长度最长,所以要弄成完全二叉树那样,而不能像普通哈夫曼树
que.push(aii(0,1));
Num += n;//代表一共有多个元素
while(Num != 1)
{
aii a;
long long Temp = 0, Max_h = 0;
for (int i = 1; i <= k; i++) //几进制就是拿几个点,比如二进制子树可以有两个分别是0,1路径编号,要是三就是0,1,2,
{
a = que.top();
Temp += a.first;//合并后的最大值
Max_h = max(Max_h, a.second);//计算最大层数
que.pop();
}//合并前k个元素
Ans += Temp;//最短长度就是每次合并后的值的和
que.push(aii(Temp,Max_h+1));//层数加以
Num -= k;//节点-k因为拿出去了多少个点
Num++;//节点+1因为放回去了
}
Length = que.top().second - 1;
cout << Ans << endl;
cout << Length;
return 0;
}
后面
这个是最优解的哈夫曼树就是完全K叉树的模样,如果不是要求最解其实很结点
每次都是将k个节点合并为1个(减少k-1个),一共要将n个节点合并为1个,如果(n-1)%(k-1)!=0 则最后一次合并时不足k个。
也就表明了最靠近根节点的位置反而没有被排满,因此我们需要加入k-1-(n-1)%(k-1)个空节点使每次合并都够k个节点(也就是利用空节点将其余的节点挤到更优的位置上)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)