7-10 修理牧场 (25 分)
农夫需要对牧场的一段栅栏进行修缮。经过测量后,他发现总共需要N块木材,并且每一块木材的长度均为整数单位Li。因此,他决定采购一根足够长且可分割成N段的木材。
但是农夫自己没有斧头,请人帮忙 saw 木材时所付报酬与其所 saw 的木材长度成正比。为了简化计算方便起见,默认将每段 saw 的木材长度作为其对应的报酬。例如,在长度为 20 的一根长棍子上希望切割出长度分别为 8、7 和 5 的三段木材。首先 saw 这根长棍子花费了 20 单位成本,并将其分割成为 12 和 8 长度的小棍子两部分;随后再次 saw 长度较长的部分(即长度为 12 的那块),花费了 12 单位成本并将其分割成为 7 和 5 长度的小棍子两部分。这样总共的成本就是 32 单位(即两次 saw 所花费用之和)。如果第一次切割选择将整根长棍子分成 15 和 5 长度的小棍子两部分,则第二次 saw 所需的成本将是更高昂的:即第二次 saw 成本高达 15 单位(因为此时较长的那一小段已经变成了原来的整个被 cut 部分),因此总成本达到 35 单位(高于之前方案)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
输入格式:
输入首先接着提供一个不超过10⁴的正整数N,这意味着我们需要将一根木头分割成N段。接下来的一行包含N个不超过50的正整数,这些数字代表每一段木头的具体长度。
输出格式:
输出一个整数,即将木头锯成N块的最少花费。
输入样例:
8
4 5 1 2 1 3 1 1
输出样例:
49
在解决这个问题时,我首先创建了三个数组:其中一个用于存储原始数据;另一个用于队列操作(将最小的两个节点相加生成的新节点被加入到队列中);最后一个用于存储非叶子节点并计算其权值。接着,在数据数组中找到两个最小的数值,并按照一定顺序构建Huffman树。经过实践发现这种方法虽然可行但操作较为繁琐。
随后编写了相应的代码,并遵循以下步骤:首先使用插入排序对数组(或队列)进行排序;接着计算该序列中的前两项之和;之后移除该序列的第一个元素(即出队操作);最后将非叶子节点的值被累加起来;从而得到最终结果
源代码:
#include<stdio.h>
int main(){
int n;
int arr[10000],q,p,sum=0,i,j,m=0,t=0,len;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
len=i;
q=0; //队列头部
p=i-1; //队列尾部
if(n==1){ //只有一根木头,不用操作
printf("0");
return 0;
}
while(1){
for (i = q+1;i < len;i++)
{
t = arr[i];
for (j = i - 1;j >= q && arr[j] > t;j--)
arr[j + 1] = arr[j];
arr[j + 1] = t;
}
arr[q+1]+=arr[q]; //最小数据相加,存到数组有效位第二位
sum+=arr[q+1]; //非叶子节点权值相加
q++; //队列首位(有效位第一位)出队
if(q==p){
printf("%d",sum);
return 0;
}
}
}
