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);
}

 





posted @ 2020-09-13 06:55  幽灵轩  阅读(347)  评论(0编辑  收藏  举报