zoukankan      html  css  js  c++  java
  • poj 3253 Fence Repair (优先队列,哈弗曼)

    题目链接:http://poj.org/problem?id=3253

    题意:给出n块木板的长度L1,L2...Ln,求在一块总长为这个木板和的大木板中如何切割出这n块木板花费最少,花费就是将木板切割前的长度。

    有个陷阱就是需要用long long 去储存

    Sample Input

    3
    8
    5
    8

    Sample Output

    34

    就是将一块长为21的木板先切成13和8,花费21。然后将13切成5和8,花费13,总花费21 + 13 = 34。

    分析:如果考虑从一块木板分割成小木板,方法数会有很多种,其实可以转化成从小木板合成大木板。

    其实就是构造一棵最优二叉树(哈夫曼树),然后求出这棵树带权路径长度,过程如下:

    题目可以转化为Huffman树构造问题 :

     

    给定 N planks of woods,

    1.   在 N planks 中每次找出两块长度最短的木板,然后把它们合并,加入到集合A中,

    2.  在集合中找出两块长度最短的木板,合并加入到集合A中,重复过程,直到集合A中只剩下一个元素

    显然,通过每次选取两块长度最短的木板,合并,最终必定可以合并出长度为 Sum(Li)的木板,并且可以保证总的耗费最少

    所以采用优先队列,每次都取出两块最短的木板,然后结果加上这两块木板长度,再入队(这两块木板长度之和),直到木板之和为一块

    #include<bits/stdc++.h>
    const long long maxn = 2e4+5;
    using namespace std;
    int main()
    {
        priority_queue<long long,vector<long long>, greater<long long> > q;
        long long n;
        scanf("%lld", &n);
        if(n == 1)
        {
            long long l;
            scanf("%lld", &l);
            printf("%d
    ", l);
            return 0;
        }
        if(n == 2)
        {
            long long l1, l2;
            scanf("%lld %lld", &l1, &l2);
            printf("%d
    ",l1+l2);
            return 0;
        }
        while(n--)
        {
            long long t;
            scanf("%lld", &t);
            q.push(t);
        }
        long long res = 0;
        do
        {
            long long t1 = q.top();q.pop();
            long long t2 = q.top();q.pop();
    //        printf("%d %d
    ", t1, t2);
            q.push(t1+t2);
            res += t1+t2;
        }while(q.size()!= 1);
        printf("%lld
    ",res);
        return 0;
    }
  • 相关阅读:
    【HDOJ6701】Make Rounddog Happy(启发式合并)
    【HDOJ6731】Angle Beats(极角排序)
    【BZOJ1132】Tro(叉积)
    【CF1236D】Alice and the Doll(set)
    Storm
    Spark
    Python基础(2)
    数据库漫谈
    Python基础(1)
    C/C++链接过程相关
  • 原文地址:https://www.cnblogs.com/Jadon97/p/6803473.html
Copyright © 2011-2022 走看看