锯木头的花费取决于要锯的那段木头的长度,为了将花费控制到最小,我们自然会想到每次锯的时候尽量让锯出来中较长的一段木头的长度尽可能的短一点,换句话说也就是让锯出来的两段木头的长度尽可能的接近。
题目给的是最终每段木头的长度,反过来想,也就是将木头拼回去,每次花费是两段木头的长度和。那么按照锯木头时的想法,每次拼木头的时候要找两段长度尽可能接近的木头进行拼合,也就是找出最短的两段木头。所以只要用一个优先队列来维护最短的木头长度即可。
我们可以发现,这种做法和哈夫曼树的构造有着惊人的相似之处。其实这道题就是哈夫曼编码应用的一个变型。木头的长度可以视为某个字符出现的次数,出现次数越少的字符在哈夫曼树中的位置就越靠近叶结点。
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main()
{
long long ans = 0,x,t1,t2;
int n;
priority_queue<long long, vector<long long>, greater<long long> > q;
cin >> n;
while(n--)
{
cin >> x;
q.push(x);
}
while(q.size()>1)
{
t1 = q.top();
q.pop();
t2 = q.top();
q.pop();
ans += t1 + t2;
q.push(t1 + t2);
}
cout << ans;
return 0;
}
这篇博客探讨了一种通过优先队列优化锯木头问题的算法,该算法与哈夫曼编码的构建过程有密切关系。作者通过反转问题,将寻找最短木头长度的过程转化为哈夫曼树构造的类似操作,每次合并最短的两段木头以最小化总花费。此外,博客还指出木头长度与字符出现频率的类比,进一步强调了这个问题在信息编码理论中的应用。
5635

被折叠的 条评论
为什么被折叠?



