本次实验为:修理牧场
1.问题描述
【题目描述】PTA(数据结构与算法题目集7-29) 农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li 个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li的总和。 但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等 于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费 20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。 如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。 请编写程序帮助农夫计算将木头锯成N块的最少花费。
2.思路分析
- 选择合适的数据结构:利用优先队列(最小堆)来存储当前待拼接的木头长度。因为每次要选择长度最短的两段木头进行拼接,最小堆能方便地取出最小值并在插入新元素后依然保持有序性(时间复杂度较低地获取最小值)。
- 模拟锯木过程:
- 不断从堆中取出最短的两段木头(堆顶元素,取出操作时间复杂度为O(logn) ,n 为堆中元素个数),将它们拼接在一起(计算长度和)。
- 把拼接后的长度加入到总花费中(因为酬金等于所锯木头的长度),然后再把拼接后的长度放回堆中,以便后续继续选择最短的进行拼接操作。
- 重复上述步骤,直到堆中只剩下一段木头,也就是所有木头都已经按照最优策略拼接完成,此时的总花费就是将原始长木头锯成指定 n 块的最少花费。
3.代码设计
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; ++i) {
cin >> nums[i];
}
priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.end());
int cost = 0;
while (pq.size() > 1) {
int min1 = pq.top();
pq.pop();
int min2 = pq.top();
pq.pop();
int sum_ = min1 + min2;
cost += sum_;
pq.push(sum_);
}
cout << cost << endl;
return 0;
}
此代码核心为计算其时间复杂度和空间复杂度得到锯木头的最少花费,通过上述代码实现,就能根据输入的需要锯成的木头块数以及各块木头的长度,计算出将木头锯成 N 块的最少花费。