题目:
农夫约翰想修复牧场周围的一小部分篱笆。 他测量围栏,发现他需要N(1≤N≤20,000)块木板,每块木板具有一定的整数长度Li(1≤Li≤50,000)个单位。 然后,他购买了一块足够长的单块长板,足以切入N块木板(即,其长度为Li的长度之和)。 FJ忽略了“锯缝”,即锯切时因锯末而损失的额外长度; 您也应该忽略它。
FJ遗憾地意识到自己没有切割木头的锯子,于是他用这长板把苔藓拖到农夫唐农场,礼貌地问他是否可以借用锯子。
壁橱资本家农夫唐(Farmer Don)不借给FJ锯,而是提议就木板中的每个N-1切割向农夫约翰收费。 切割一块木头的费用正好等于它的长度。 切割一块长度为21的木板需要21美分。
然后,农夫唐让农夫约翰决定切割木板的顺序和位置。 帮助农夫约翰确定他可以用来制作N块木板的最低金额。 FJ知道他可以按各种不同的顺序切割木板,这将导致不同的费用,因为最终的中间木板长度不同。
思路:由于木板的切割顺序不确定,切割方法有很多,怎么找最小花费。。。
我们可以利用二叉树原理来描述切割木板。要想总花销最小,可以使用哈夫曼树的特点,最短的板当做最深的叶子结点,构建哈夫曼树,最后的花费肯定是最小的。
如何构造:
1.将给出的几个长度从小到大排序
2.取最短的两个合并,当做一个新的长板
3.重复,直到最后组合成一个木板。
但是每次最短两个木板相加后都需要整体排序,可能超时
所以可以用STL,自动排序.
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <stack>
#include <algorithm>
#define ll long long
using namespace std;
int main()
{
int n,i,j,t,x;
while(~scanf("%d",&n))
{
priority_queue<int,vector<int>,greater<int> > q;
for (i=0;i<n;i++)
{
scanf("%d",&x);
q.push(x);
}
ll sum=0,a=0,b=0;
while(!q.empty())
{
a=q.top(),q.pop();
if (q.empty())
break;
b=q.top(),q.pop();
sum+=(a+b);
q.push(a+b);
}
printf("%lld
",sum);
}
return 0;
}
/*
因为朴素的HuffmanTree思想是:
(1)先把输入的所有元素升序排序,再选取最小的两个元素,把他们的和值累加到总费用
(2)把这两个最小元素出队,他们的和值入队,重新排列所有元素,重复(1),
直至队列中元素个数<=1,则累计的费用就是最小费用
但是STL貌似有个自动排序呀
*/