1360: plank 栅栏修复

题目地址:http://210.43.24.243/problem.php?id=1360

1360: plank

题目描述

农民 John 希望修复围绕农场的一小段围栏。他测量了一下,发现需要 N (1 <= N<= 20,000)根木头,每根都有某一个整数长度 Li (1 <= Li <= 50,000) 单位长度。他买了一根很长的很长的木头,正好能够锯出他所需要的 N 根木头。(即它的长度正好等于 Li 的总和) FJ 忽略锯口,锯掉的木屑产生的长度损失忽略不计,你也可以忽略它。FJ 遗憾的发现他自己没有用于切木头的锯子,所以他就带着那根很长的木头来到了农民Don 的农场,想问他借一个锯子。农民 Don 是一个保守的资本家,他不愿意借锯子给 FJ ,但愿意自己来切这 N-1 刀,每一次都向 FJ 收取费用。每次的收费正好等于你要锯的那根木头的总长度。例如,你要锯一根长度为 21 的木头,就花费 21 分钱。农民 Don 然后让农民 John 自己决定每次锯木头的顺序和位置。帮助农民 John 确定锯出这 N 根木头的最小总花费。 FJ 知道可以有很多种不同的切割方式,不同的方式可能得到不同的总花费,这是因为木头在锯的过程中的长度不一。

输入

* Line 1: 一个整数 N,表示要锯出的木头数
* Lines 2..N+1: 每行一个整数,表示每根木头的长度。

输出

* Line 1: 一个整数,表示他最少需要多少分钱,锯 N-1 下,锯出所有需要的木头。

样例输入

3
8
5
8

样例输出

34

提示

图论-树

来源

图论 

 

 哈夫曼树(Huffman tree),又名最优树,指给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。

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

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

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

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

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;


int main()
{
    long long int sum;//sum定义为long long 防止出错
    int n;
    while(~scanf("%d",&n))
    {
        int a,b,t;
        priority_queue<int,vector<int>,greater<int> >q;
        for(int i=0;i<n;i++)
        {
            int t;
            scanf("%d",&t);
            q.push(t);
        }
        sum=0;
        if(q.size()==1)
        {
            sum+= q.top();
            q.pop();
        }
        while(q.size()>1)
        {
            a=q.top();
            q.pop();
            b=q.top();
            q.pop();
            t=a+b;
            sum+=t;
            q.push(t);//找出两个最小的  合并之后在放入队列中
        }
        printf("%lld\n",sum);
    }
    return 0;
}

参考博客:https://blog.csdn.net/zw792346763/article/details/79902082

https://blog.csdn.net/gao_ben_15/article/details/74652652

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值