贪心算法基础之聪明的工匠 hunnu OJ 10611 acm,huffman算法思想

来源:互联网 发布:全球地名数据库 编辑:程序博客网 时间:2024/06/06 03:48

题目来自湖南师范大学acm,网址:点击打开链接


问题:

一位老木匠需要将一根长的木棒切成N段。

每段的长度分别为L1,L2,......,LN(1 <= L1,L2,…,LN <= 1000,且均为整数)个长度单位。

我们认为切割时仅在整数点处切且没有木材损失。

木匠发现,每一次切割花费的体力与该木棒的长度成正比,不妨设切割长度为1的木棒花费1单位体力。

例如:若N=3,L1 = 3,L2 = 4,L3 = 5,则木棒原长为12,木匠可以有多种切法,

如:先将12切成3+9.,花费12体力,再将9切成4+5,花费9体力,一共花费21体力;

还可以先将12切成4+8,花费12体力,再将8切成3+5,花费8

输入

第1行:1个整数N(2 <= N <= 50000)第2 - N + 1行:每行1个整数Li(1 <= Li <= 1000)。

输出

输出最小的体力消耗。

输入示例

3345

输出示例

19

分析:


本题的解题思想运用的是Huffman算法。具体实现借用了优先队列,并没有套用huffman代码


一开始没理解好题意,以为要切成的线段是按顺序排好的。

正确题意是:不管从哪个位置切,只要最后能切出那些长度的线段就行。


这样想,我们第一刀切的时候,不管切哪,耗费体力都一样。


因此,我们要尽量在前几刀多切掉一些,这样后面切的时候才能更省体力。


也就是说,我们把短的尽量留到最后再切,就会更省体力。


为了方便计算,不妨倒着来,假设我们把木棍全切好了,现在把他们按最优方案复原


这样,就可以每次选出两个最短的接起来,组成新木棍。然后再去两个最短的,以此类推。


每次接的时候累加上耗费的体力(即线段长度)


如此一来,优先队列解题最合适了。优先出小的



代码:

#include<stdio.h>#include<algorithm>#include<queue>using namespace std;int main(){int n;priority_queue<int,vector<int>,greater<int> > q;while(scanf("%d",&n)!=EOF){while(!q.empty()) q.pop();for(int i=0;i<n;i++){int len;scanf("%d",&len);q.push(len);}int ans=0;while(q.size()>1){int x=q.top();q.pop();int y=q.top();q.pop();ans+=x+y;q.push(x+y);}printf("%d\n",ans);}return 0;}




0 0