4-4-哈夫曼树 修理牧场 (25分)
4-4-哈夫曼树 修理牧场 (25分)
农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li的总和。
但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
输入格式:
输入首先给出正整数N(≤),表示要将木头锯成N块。第二行给出N个正整数(≤),表示每段木块的长度。
输出格式:
输出一个整数,即将木头锯成N块的最少花费。
输入样例:
8
4 5 1 2 1 3 1 1
输出样例:
49
解题思路
显然这是一道,哈夫曼树
就是应用堆的操作,很基础的堆的插入删除
众所周知,堆是一个完全二叉树
插入:在尾部插入,再比较父子节点的大小关系,进行调整堆
删除:取出堆顶之后,将最后一个元素补在堆顶,再进行调整堆
简单理解题意就是一个逆向思维,哈夫曼树的正操作过程
实现不难,熟练就行
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; const int Min=0; const int Max=10000000; typedef struct Node* Heap; struct Node{ int* Data; int size; }; Heap Creatheap(int n){ Heap H=(Heap)malloc(sizeof(struct Node)); H->Data=(int*)malloc(2*(n+1) * sizeof(int)); H->size=0; H->Data[0]=Min;//设置哨兵 return H; } int ans; Heap Insert(Heap H,int n){ int fa=++H->size; for(;H->Data[fa/2]>n;fa/=2){ H->Data[fa]=H->Data[fa/2]; } H->Data[fa]=n; return H; } int DeleteMin (Heap H){ int fa,son; int sma=H->Data[1]; int x=H->Data[H->size--]; for(fa=1;fa*2<= H->size;fa=son){ son=fa*2; if(son!=H->size){ if(H->Data[son] > H->Data[son+1])son++; } if(x< H->Data[son])break;//比他的两个儿子都小 else H->Data[fa]=H->Data[son]; } H->Data[fa]=x; return sma; } int main(){ int n,x; scanf("%d",&n); Heap H=Creatheap(n); for(int i=0;i<n;i++){ scanf("%d",&x); H=Insert(H,x); } n--; while(n--){ x=DeleteMin(H)+DeleteMin(H); ans+=x; //printf("%d\n",ans); H=Insert(H,x); //将最小两数之和,插入到堆中 } printf("%d",ans); }
我是一颗水灵灵的大白菜,
农民伯伯辛勤的耕种着我,
把我带到了菜市场
拿着喷头对着我浇水,
还一边说“好菜啊好菜”