农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li 的总和。
但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
输入格式:
输入首先给出正整数N(≤104 ),表示要将木头锯成N块。第二行给出N个正整数(≤50),表示每段木块的长度。
输出格式:
输出一个整数,即将木头锯成N块的最少花费。
输入样例:
8
4 5 1 2 1 3 1 1
输出样例:
49
哈夫曼树,又称最优树,是一类带权路径长度最短的树。
你拿到这道题目肯定会疑惑——这锯木头跟树结构有什么关系?跟哈夫曼树又有什么关系?
这就是这道题目的巧妙之处了,它利用了解构的手段,每一次锯木相当于二叉树的一个分支,叶结点的权重就是该结点代表的木头长度,非叶结点就是子节点的权重和。
当然你不需要写出真正的树结构,只需要得到结果就可以了,利用最小堆是最好的选择。
这道题思路比较难以理解,代码很好写
尤其要注意的是堆的删除操作,这个操作不太好实现,思路是把堆中最后一个元素提到堆顶部,然后循环调整
之所以是要用child中较小的那一个,是因为要将child提升为parent,需要满足非叶子节点小于其child的条件,总之,delete操作应当多写几遍,加以熟悉。
我发现自己也就能写写这种,4.26这种复杂题目真的写不出来(悲
代码如下:
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
#define Mindata 0
#define MAXdata 500000
#define Scale 10000
typedef struct node* Heap;
typedef int ElementType;
int ans = 0;
struct node {
int* Data;
int size;
int capacity;//直接定义为无限大
};
Heap creatminheap(int maxsize) {
Heap H = (Heap)malloc(sizeof(struct node));
H->Data = (int*)malloc(2*(maxsize+1) * sizeof(int));
H->size =0;
H->Data[0] = Mindata;
return H;
}
Heap insert(Heap H, int n) {
int mom = ++H->size;
for (; H->Data[mom/2] > n; mom /= 2)//注意是mom/2
H->Data[mom] = H->Data[mom / 2];
H->Data[mom] = n;
return H;
}
ElementType DeleteMin(Heap H)
{
int Parent, Child;
ElementType MinItem, X;
MinItem = H->Data[1];
X = H->Data[H->size--];
for (Parent = 1; Parent * 2 <= H->size; Parent = Child) {
Child = Parent * 2;
if ((Child != H->size) && (H->Data[Child] > H->Data[Child + 1]))
Child++; /* Child指向左右子结点的较小者 */
if (X < H->Data[Child]) break; /* 找到了合适位置 */
else /* 下滤X */
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
return MinItem;
}
int main() {
int n,tmp;
cin >> n;
Heap H = creatminheap(n);
for(int i=0;i<n;i++){
cin >> tmp;
H=insert(H, tmp);
}
n--;
while (n--) {//砍n-1次
tmp = DeleteMin(H) + DeleteMin(H);
ans += tmp;
H = insert(H, tmp);
}
cout << ans;
}