题解:AcWing 148 合并果子

【题目来源】

AcWing:148. 合并果子 - AcWing题库

【题目描述】

在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。

每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 \(n-1\) 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 \(1\) ,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

例如有 \(3\) 种果子,数目依次为 \(1\)\(2\)\(9\) 。可以先将 \(1\)\(2\) 堆合并,新堆数目为 \(3\) ,耗费体力为 \(3\) 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 $12 $,耗费体力为 $12 $。所以多多总共耗费体力 \(=3+12=15\) 。可以证明 \(15\) 为最小的体力耗费值。

【输入】

共两行。 第一行是一个整数 \(n(1\le n\le 10000)\) ,表示果子的种类数。

第二行包含 \(n\) 个整数,用空格分隔,第 \(i\) 个整数 \(a_i(1\le a_i\le 20000)\) 是第 \(i\) 种果子的数目。

【输出】

一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 \(2^{31}\)

【输入样例】

3 
1 2 9 

【输出样例】

15

【算法标签】

《AcWing 148 合并果子》 #贪心# #Huffman树#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n;  // 输入的数字个数
    cin >> n;

    // 定义一个小根堆(优先队列),用于存储数字并快速获取最小值
    priority_queue<int, vector<int>, greater<int>> heap;

    // 输入 n 个数字,并将它们加入小根堆
    while (n--)
    {
        int x;
        cin >> x;
        heap.push(x);  // 将数字 x 加入小根堆
    }

    int res = 0;  // 用于存储最终的结果(最小代价)

    // 当堆中还有多于一个元素时,继续合并
    while (heap.size() > 1)
    {
        // 取出堆中的两个最小元素
        int x = heap.top(); heap.pop();  // 取出堆顶元素(最小值)并删除
        int y = heap.top(); heap.pop();  // 再次取出堆顶元素(次小值)并删除

        // 将这两个元素合并,并将合并的代价累加到结果中
        res += x + y;  // 合并代价为 x + y

        // 将合并后的新元素(x + y)重新加入堆中
        heap.push(x + y);
    }

    // 输出最终的最小代价
    cout << res << endl;

    return 0;
}

【运行结果】

3 
1 2 9
15
posted @ 2026-02-27 09:21  团爸讲算法  阅读(2)  评论(0)    收藏  举报