我们有 n 段木头,目标是通过不断将木头切成小段,直到分成指定的 n 段。每次切割的代价是当前木头的长度,因此我们希望每次切割代价最小。
具体地,可以用一种贪心策略:每次将最短的两段木头拼接起来,减少总的切割费用。
哈夫曼树模型:
每次选择长度最小的两段木头进行拼接,形成一段新的木头,花费为这两段木头的总长度。然后,将新的木头加入可选择的木头段中,重复这个过程直到所有木头拼接成一个整体。
为了高效地找到最短的两段木头,我们可以使用**优先队列(最小堆)**来实现。
贪心策略:
每次从剩下的木头中选出两段最短的木头进行拼接,将它们的长度相加,并将结果插回到队列中,重复此过程直到没有木头可以再拼接。
具体步骤:
将所有木头的长度存入优先队列(最小堆)。
每次从队列中取出两个最短的木头段,将它们拼接(相加长度),累加代价。
将新形成的木头段再次放入队列,继续上述操作直到所有木头拼接完成。
最终累加的代价就是最小的锯木代价。
三,源代码
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
// 优先队列(最小堆),用于存储木头段的长度
priority_queue<int, vector<int>, greater<int>> pq;
// 读取每段木头的长度
for (int i = 0; i < n; ++i) {
int length;
cin >> length;
pq.push(length);
}
int totalCost = 0;
// 每次取出最短的两段木头,合并并计算花费
while (pq.size() > 1) {
int first = pq.top(); pq.pop();
int second = pq.top(); pq.pop();
int cost = first + second;
totalCost += cost;
// 将新的木头段长度插入优先队列
pq.push(cost);
}
// 输出最少的总花费
cout << totalCost << endl;
return 0;
}