当前位置:首页 > 提高组 > 2004年NOIP提高组合并果子(洛谷P1090)题解:优先队列与贪心算法的完美应用

2004年NOIP提高组合并果子(洛谷P1090)题解:优先队列与贪心算法的完美应用

2个月前 (08-24)

2004年NOIP提高组合并果子(洛谷P1090)题解:优先队列与贪心算法的完美应用 贪心策略 优先队列 NOIP提高组 NOIP题解 洛谷题解 C++ 第1张

一、题目解读

合并果子(洛谷P1090)是2004年NOIP提高组的一道经典题目,原题链接:https://www.luogu.com.cn/problem/P1090。题目描述了一个果园场景:需要将N堆果子合并成一堆,每次合并消耗体力为两堆果子的重量之和,目标是通过设计合并顺序,使总消耗体力最小。数据范围要求1≤N≤10000,每堆果子重量1≤ai≤20000,需输出最小体力值。

二、解题思路

核心思路为贪心算法:每次优先合并当前最小的两堆果子,以降低后续合并的消耗。实现关键在于利用**优先队列最小堆)**自动维护果子堆的重量排序,确保每次取出的两堆果子重量最小,从而保证整体消耗最优。该策略符合哈夫曼(最优二叉树)的构建思想,即权值小的节点优先靠近叶节点,减少路径长度。

三、解题步骤

1. 输入处理:读取果子种类数N及每堆重量,存入优先队列q(小顶堆)。

2. 合并过程:

○ 循环直至队列仅剩一堆:

    弹出队首两堆果子a、b,计算合并消耗sum += a + b;

    将新堆a+b重新入队q,维持堆有序性。

3. 输出结果:最终sum即为最小体力消耗值。

四、代码与注释

#include <iostream>  
#include <queue>  
using namespace std;  

int main() {  
    int n, sum = 0;  
    cin >> n; // 输入果子种类数N  

    // 创建小顶堆优先队列,自动维护元素升序  
    priority_queue<int, vector<int>, greater<int>> q;  

    for(int i = 0; i < n; ++i) {  
        int weight;  
        cin >> weight; // 输入每堆果子重量  
        q.push(weight); // 初始化堆  
    }  

    while(q.size() > 1) { // 循环至仅剩一堆  
        int a = q.top(); q.pop(); // 取出最小两堆果子  
        int b = q.top(); q.pop();  
        sum += a + b; // 累加当前合并消耗  
        q.push(a + b); // 新堆入列  
    }  

    cout << sum << endl; // 输出最小体力值  
    return 0;  
}

注释解析:

● 优先队列q通过greater<int>参数指定为小顶堆,确保q.top()始终返回当前最小重量堆。

● 循环条件q.size() > 1保证合并次数为N-1,符合题目要求。

● sum变量累计每次合并的消耗,最终结果即为最优解。

五、总结

本解法通过贪心策略与优先队列的结合,将复杂度为O(NlogN)的合并问题高效解决。关键在于“局部最优(每次最小合并)导致全局最优”的证明,体现了贪心算法的核心思想。实际应用中,该思路可扩展至类似资源合并优化场景,如哈夫曼编码树的构建。代码简洁且符合竞赛要求,是学习优先队列与贪心算法的经典案例。



原创内容 转载请注明出处

分享给朋友:

相关文章

力扣第1984题精解:如何通过排序将时间复杂度优化到O(n log n)?

力扣第1984题精解:如何通过排序将时间复杂度优化到O(n log n)?

题目解读给定一个整数数组和一个整数 k,需要找到所有大小为 k 的子数组中最大值与最小值的差值的最小值。例如,数组 [9,4,1,7] 中若 ...

力扣LCR182:字符串操作三连 从基础拼接到底层指针优化

力扣LCR182:字符串操作三连 从基础拼接到底层指针优化

题目重解需要将密码字符串从第target个字符开始进行重新排列,形成新的动态密码。例如输入"password"和target=3,结果应为"swordpas"。...

力扣119题:从O(n²)到O(2n):杨辉三角高效空间优化

力扣119题:从O(n²)到O(2n):杨辉三角高效空间优化

题目重解:给定一个非负索引 rowIndex,返回杨辉三角的第 rowIndex 行。不同于生成整个杨辉三角,这道题要求我们只返回特定行,且空间复杂度应尽可能优化。例如输入3,需要返回[1,3,3,1...

力扣35:二分法在搜索插入位置中的运用

力扣35:二分法在搜索插入位置中的运用

有序数组的定位在一个严格递增的数字序列中,每个元素都有其确定的位置。当新元素试图加入时,我们需要回答两个问题:它是否已经存在?如果不存在,它应该插入在哪里?这道题要求我们在O(log n)时间内完成这...

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

题目重解:数字三角形是一个经典的动态规划问题,给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们需要找到一条路径,使得路径上经过的数字总和最大。这个问题可以很...

力扣144:递归之美 轻松掌握二叉树前序遍历

力扣144:递归之美 轻松掌握二叉树前序遍历

题目解读二叉树的前序遍历是一种基础但重要的树遍历方式,其遍历顺序为:先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。给定一个二叉树的根节点,我们需要按照这个顺序访问所有节点,并将它们...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。