Advertisement

修理牧场(哈夫曼树)

阅读量:

7-1 维护牧场(25 分)
农夫计划修复牧场的一段围栏,并进行了详细测量以确定所需材料的数量与规格。他计算出总共需要N块木材,并确定每一块木材的标准长度为整数L_i个单位长度。随后他采购了一根足够长并可切割成指定数量木材的大木材料板;其总长度等于所有L_i之总和。

但是农夫自己没有工具,请人切割木材时所付报酬与其所切割木材的长度呈正比。为了便于理解,在举例时假设酬金即等于被切割木材段落的实际长度。例如要将一根长为20米(或其他单位)的木材分割成8米、7米和5米三段,则应首先进行一次成本较高的切割操作:第一次切割耗费的时间或费用(这里用数值表示)是20单位,并将其分成12米和8米两段;随后再对剩下的12米木材进行第二次切割:耗费时间或费用是12单位,并将其切成7米和5米两段;总费用即为此两项之和:32单位。如果他第一次就切下15米和5米两段,则第二次切割耗费的时间或费用是15单位……总费用则达到35单位(超过之前的最低成本32单位)。

请编写程序帮助农夫计算将木头锯成N块的最少花费。

输入格式:
首先包含一个不超过10^4的正整数N,在线性时间内计算出满足条件的结果值并将其返回。随后包含一行由不超过50的正整数组成的内容。
输出格式:
最终结果是一个非负整数值。

输入样例:
8
4 5 1 2 1 3 1 1
输出样例:
49
根据题意可知,求最少花费即为构造哈夫曼树的过程。

代码如下:

复制代码
    #include<iostream>
    #include<vector>
    using namespace std;
    void Sum(vector<int> &arr)
    {
    int total=0;//总花费
    while(arr.size()>1)
    {
        int min1=arr[0];//权值最小的两个值
        int pos1=0,pos2=0;//当前最小结点的下标
        int tmp=0;//保存当前两个最小结点的权值之和
        for(int i=1; i<arr.size(); i++)
        {
            if(arr[i]<min1)
            {
                min1=arr[i];
                pos1=i;
            }
        }
        tmp+=min1;
        arr.erase(arr.begin()+pos1);
    
        int min2=arr[0];//删除一个数之后的第一个元素
        for(int i=1; i<arr.size(); i++)
        {
            if(arr[i]<min2)
            {
                min2=arr[i];
                pos2=i;
            }
        }
        tmp+=min2;
        arr.erase(arr.begin()+pos2);
        total+=tmp;
        arr.push_back(tmp);
    }
    cout<<total;
    }
    int main()
    {
    int N,W;
    cin>>N;
    vector<int> weight;
    for(int i=0; i<N; i++)
    {
        cin>>W;
        weight.push_back(W);
    }
    Sum(weight);
    
    return 0;
    }

全部评论 (0)

还没有任何评论哟~