農夫約翰需將長木板鋸成 N 塊指定長度。每次鋸切花費等於當前木板長度。求最小總花費。N ≤ 20,000,長度 ≤ 50,000。
經典哈夫曼樹構建:每次合併最小的兩塊木板,花費為兩者之和。使用最小堆(優先隊列)實現。
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
int main() {
int N;
while (cin >> N) {
priority_queue<int, vector<int>, greater<int>> pq;
for (int i = 0; i < N; i++) {
int x; cin >> x;
pq.push(x);
}
ll ans = 0;
while (pq.size() > 1) {
int a = pq.top(); pq.pop();
int b = pq.top(); pq.pop();
ans += a + b;
pq.push(a + b);
}
cout << ans << endl;
}
return 0;
}
N 次插入、2(N-1) 次取出、N-1 次插入,每次 O(log N),總時間 O(N log N),空間 O(N)。