Advertisement

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

全部评论 (0)

还没有任何评论哟~