poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

时间:2023-03-09 04:05:41
poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

地址 http://poj.org/problem?id=3253

poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

题解

本题是<挑战程序设计>一书的例题

根据树中描述 所有切割的代价 可以形成一颗二叉树

而最后的代价总和是与子节点和深度相关的 由于切割的次数是确定的 该二叉树的节点就是确定的。

也就是说我们可以贪心的处理  最小长度的子节点放在最下面

如图

poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

ac代码如下 使用了堆 记录每次最小的元素

堆的使用真的不是很方便 , 另外还需要注意 爆int 所以需要使用long long 记录元素的和

 #include <iostream>
#include <algorithm>
#include <vector>
#include <assert.h> using namespace std; /*
poj 3253
有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度
给定各个要求的小木板的长度,及小木板的个数n,求最小费用
提示:

3
8 8 5为例: 先从无限长的木板上锯下长度为 21 的木板,花费 21
再从长度为21的木板上锯下长度为5的木板,花费5
再从长度为16的木板上锯下长度为8的木板,花费8
总花费 = 21 + 5 + 8 = 34
*/ int main()
{
int n; long long ret = ;
cin >> n;
vector<int> wood(n);
for (int i = ; i < n; i++) {
cin >> wood[i];
}
make_heap(wood.begin(), wood.end(), greater<int>()); while (wood.size() != ) { pop_heap(wood.begin(), wood.end(), greater<int>());
long long total = wood.back();
wood.pop_back(); pop_heap(wood.begin(), wood.end(), greater<int>());
total += wood.back();
wood.pop_back(); ret += total;
wood.push_back(total);
push_heap(wood.begin(), wood.end(), greater<int>());
} cout << ret << endl; return ;
}
 #include <iostream>
#include <queue> #include <stdio.h> using namespace std; typedef long long LL; const int MAX_N = ;
int n, L[MAX_N]; void solve()
{
LL ans = ;
priority_queue<int, vector<int>, greater<int>> que;
for (int i = ; i < n; i++) {
que.push(L[i]);
} while (que.size() > ) {
int l1, l2;
l1 = que.top();
que.pop();
l2 = que.top();
que.pop(); ans += l1 + l2;
que.push(l1 + l2);
}
printf("%lld\n", ans);
} int main()
{
scanf("%d", &n); for (int i = ; i < n; i++) {
scanf("%d", &L[i]);
} solve();
}

stl 堆