AcWing 149. 荷马史诗
原题链接
简单
作者:
软嘟嘟
,
2020-08-31 21:40:45
,
所有人可见
,
阅读 657
就简单的说一下就是一个哈夫曼树,用来合并k的最小的点这样一直下去就可以活得最短长度和最短高度,其实不难看出就是用一个优先队列来维护一个小根堆。其他讲解用代码来看吧~
#include<bits/stdc++.h>
using namespace std;
struct node{
long long w,h;//w代表单词个数也就是宽度,h代表字符串长度 也就是高度
node(long long W,long long H)
{
w=W,h=H;
}
};
bool operator <(node a,node b)
{
if(a.w==b.w) return a.h>b.h;//如果单词个数相等,返回高度小的优先
return a.w>b.w;
}//维护小根堆
int n,k,cnt=0;//cnt用来记录结点的个数 ,
long long maxh,temp,ans=0;//ans来维护最短权值,也就是最短字符串的长度
//maxh用来维护最长字符串的最短长度其实就是树的高度
priority_queue<node>q;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>temp;
q.push((node){temp,1});
}
if((n-1)%(k-1)!=0) cnt=(k-1)-(n-1)%(k-1);
//这里重点说一下,因为哈夫曼树有一个性质,就是n个叶子结点有2n-1个结点
//因为我们每次要合并最小k个结点,相当于减少k-1个点, 这里我们要判断最后一次合并是否
//可以满足k-1个结点如果满足不了就要把他排满
for(int i=1;i<=cnt;i++) q.push((node){0,1});
cnt+=n;
while(cnt>1)
{
temp=maxh=0;
for(int i=1;i<=k;i++)
{
temp+=q.top().w;
maxh=max(maxh,q.top().h);
q.pop();
}
ans+=temp;
q.push((node){temp,maxh+1});
cnt-=k-1;
}
cout<<ans<<endl;
cout<<q.top().h-1<<endl;
//因为我们规定空节点的高度是1,所以树的实际高度要-1
return 0;
}
٩(๑>◡<๑)۶
……~……