POJ 3253 Fence Repair(贪心+优先队列)

来源:互联网 发布:指绘软件sketchbook 编辑:程序博客网 时间:2024/05/20 19:31

原题地址

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

题意:农夫准备把总长度为L的木板切割成N块长度为L1,L2…LN的小木板,对于这N-1次切割,每次切割木板的费用为这块木板的长度。安排切割的次序,使得这N-1次切割的费用最少。
例如长度为21的木板要切成长度为5,8,8的三块木板。长度为21的木板切为长为13和8的木板时,费用为21;再将13切为5+8时,费用为13;总费用为21+13=34。

解题思路

这道题与之前做过的一道合并水果消耗最少体力值的题目很像,都是明显的贪心算法的应用,当然实现这里的贪心都是用huffman树。

贴上书上给的思路:
本题思路图

学过哈夫曼编码的不难看出来这就是最优编码的问题。因此,每次都从板的集合里取出最短的两块板,将它们拼合后的长度之和加入集合中等待继续合并,不停重复直到合并为根节点(总长度)。

用最小堆+优先队列的数据结构实现非常方便,每次维护堆的复杂度为O(logN),一共要进行O(N)次维护堆,所以算法复杂度为O(NlogN)。

AC代码

#include <iostream>#include <algorithm>#include <queue>using namespace std;int main(){    ios::sync_with_stdio(false);    //优先队列实现最小堆    priority_queue<int, vector<int>, greater<int> > pq;    int n, x;    cin >> n;    for (int i = 0; i<n; ++i)    {        cin >> x;        pq.push(x);    }    long long ans = 0; //注意数据范围,可能会超出int导致WA    int L1,L2;    while (pq.size() > 1) //循环到只剩一块木板为止    {        L1 = pq.top(); pq.pop(); //最短板        L2 = pq.top(); pq.pop(); //次短板        //合并木板并插入队列        ans += L1+L2;        pq.push(L1+L2);    }    cout << ans << endl;    return 0;}

算法复杂度:O(NlogN)
耗时:64ms

0 0
原创粉丝点击