POJ - 3253 - Fence Repair(哈夫曼树 + 优先队列)
题意:把一块木板分成n块(1 <= n <= 20000),锯完后的这n块已经给你,你每次可以把一块木板锯成两块,开销为两块之和,求最小的开销。
哈夫曼树直接每次选最小的两块木板即可。
代码如下:
#include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<list> #define fin freopen("in.txt", "r", stdin) #define fout freopen("out.txt", "w", stdout) #define pr(x) cout << #x << " : " << x << " " #define prln(x) cout << #x << " : " << x << endl #define Min(a, b) a < b ? a : b #define Max(a, b) a < b ? b : a typedef long long ll; typedef unsigned long long llu; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const ll LL_INF = 0x3f3f3f3f3f3f3f3f; const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f; const double pi = acos(-1.0); const double EPS = 1e-6; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const ll MOD = 1e9 + 7; using namespace std; #define NDEBUG #include<cassert> const int MAXN = 100 + 10; const int MAXT = 10000 + 10; int main(){ int n; while(scanf("%d", &n) == 1){ priority_queue<int, vector<int>, greater<int> > q; int tmp; for(int i = 0; i < n; ++i){ scanf("%d", &tmp); q.push(tmp); } ll ans = 0; while(--n){ int u = q.top(); q.pop(); int v = q.top(); q.pop(); int sum = u + v; ans += sum; q.push(sum); } printf("%lld\n", ans); } return 0; }