当前位置: 首页 > news >正文

洛谷P1090 [NOIP 2004 提高组] 合并果子 题解

P1090 NOIP 2004 提高组 合并果子 题解

此文章在洛谷上同步发表

题目大意

题目传送门
现在有 \(n\) 堆果子,每堆果子的重量为 \(a_i\),你要进行 \(n - 1\) 次合并。每次合并会把两堆果子合并成一堆果子,合并需要花费的体力为这两堆果子的重量之和,合并后果子的重量也为这两堆果子的重量之和。现在让你求出 \(n - 1\) 次合并花费的最小总体力。

思路

贪心思路

首先,很容易想到一个贪心:每次取重量最小的两堆果子,再取合并后重量最小的两堆果子,直到只有一堆果子为止。

证明过程

现在就要证明这个贪心,这里不妨先证明小范围贪心正确,再证明推导到大范围正确,就可以证明这个贪心正确。

step 1: 证明小范围贪心正确

假设现在只有 3 堆果子,果子的数量分别为 \(a,b,c\),假设 \(a \le b \le c\)\(a,b,c\) 的顺序与答案无关),现在开始需要先取 \(a, b\) 一定是最优的。

第一种情况:先取 \(a, b\),最终答案为 \((a + b) + (a + b + c) = 2a + 2b + c\)

第二种情况:先取 \(a, c\),最终答案为 \((a + c) + (a + b + c) = 2a + b + 2c\)

第二种情况:先取 \(b, c\),最终答案为 \((b + c) + (a + b + c) = a + 2b + 2c\)

现在需要比较 \(2a + 2b + c,2a+b + 2c,a+2b+2c\) 的大小关系。

因为三个式子都含有 \(a + b + c\),所以可以消掉 把三个式子同时减去 \(a + b + c\)

现在问题就变成了比较 \(a + b,a + c,b+c\) 的大小关系。

因为 \(a\le b \le c\),所以 \(a + b \le a + c \le b + c\)

所以第一种情况(先取 \(a, b\))一定是最优的。

再举个例子说明,比如 \(a = 3, b = 5, c = 9\)

第一种情况(先取 \(a,b\))的答案是 \(2a + 2b + c = 25\)

第二种情况(先取 \(a,c\))的答案是 \(2a + b + 2c = 29\)

第三种情况(先取 \(b,c\))的答案是 \(a + 2b + 2c = 31\)

通过比较也可以发现第一种情况(先取 \(a, b\))是最优的。

step 2: 证明推导到大范围也正确

假设有 \(n(n > 3)\) 堆果子,合并完 \(n - 3\) 次之后,还剩 3 堆果子,可以用类似的方法证明取重量最小的两堆果子是最优的。

因此,取重量最小的两堆果子一定是最优的。

代码实现

选择 priority_queue 及使用方法

现在需要一种数据结构,能动态找到数据结构中最小值和次小值,并删除他们,再插入他们的和。

我这里采用的是 stl 库中的 priority_queue(优先队列,也被称为堆),可以在 \(O( \log n)\) 的时间复杂度内插入、查询优先队列中最大 / 最小值、删除优先队列中最大 / 最小值。

priority_queue 的使用方法如下。

//定义方法
#include <queue>//需要的头文件
priority_queue<int>q1;//定义一个大根堆,查询和插入的是最大值
priority_queue<int, vector<int>, greater<int>>q1;//定义一个小根堆,查询和插入的是最小值//使用方法
q1.push(7);//往大根堆内插入一个值7
q1.push(4);//插入4
q1.push(12);//插入12
q1.top();//查询大根堆内的最大值,此时返回值为12
q1.pop();//删除大根堆内的最大值(删除12),没有返回值
q1.size();//查询优先队列数的个数,此时返回值为2
q1.top();//此时的最大值变成了7,所以返回7//小根堆的使用方法与大根堆的使用方法一样
q2.push(9);//插入一个数9
q2.top();//查询小根堆内最小值,返回9
q2.push(1);//插入1
q2.pop();//删除小根堆内最小值(删除1),同样没有返回值
q2.push(3);//插入3
q1.size();//查询优先队列数的个数,此时返回值为2
q2.top();//此时小根堆内的值为3和9,返回3

算法流程

输入输出我就不在这里说了,请读者自行思考。
1. 定义优先队列(小根堆)。
2. 将每堆果子的重量放进优先队列。
3. 取出小根堆中最小值和次小值,统计答案,放入他们的和。
4. 重复步骤三,直到只有一堆果子。

Code(只展示关键代码)

priority_queue<int, vector<int>, greater<int>>q;//1.定义小根堆
//2.将每堆果子的重量放进优先队列
//我在这里不放了,请读者自行思考
long long sum = 0;
while (q.size() > 1){//4.重复步骤三,直到只有一堆果子。int a1 = q.top();q.pop();int a2 = q.top();q.pop();//取出a1和a2,即最小值和次小值sum += a1 + a2;//统计答案q.push(a1 + a2);//放入他们的和
}
http://www.jsqmd.com/news/280096/

相关文章:

  • 2026最新环保板材\_实木板\_装饰板材\_欧松板\_柜子定制板材\_全屋定制板材\_多层板\_生态板\_木纹板企业首选材推荐千山板材:质价比之选,这家品牌实力领跑
  • hipDF AMD GPU 支持的Pandas,类似cuDF
  • 学术写作利器:主流论文工具功能对比与实战场景解析
  • 关于spfa,它又活了
  • 文科核心期刊发表指南:AI助力高效投稿
  • 2025冬 超级无敌挂分大王
  • 扩充练习—有理函数
  • 教师必看!国内发成绩小程序大盘点
  • Agentic-KGR:多智能体强化学习驱动的知识图谱本体渐进式扩展技术
  • 瞬维智能:房产获客的精准革命,让每一份投入都开出确定的花
  • 稀土合金回收利用:资源闭环新路径,产业盈利与环保双赢
  • 学Simulink--电机控制架构与算法实现​场景示例:基于Simulink的电机电流环PI参数整定仿真
  • P6822 [PA 2012 Finals] Tax 题解
  • 基于Springboot+Vue的校园二手书交易系统(源码+lw+部署文档+讲解等)
  • UVA1464 Traffic Real Time Query System 题解
  • B4172 学习计划 题解
  • 基于C++的《Head First设计模式》笔记——模式合作
  • 解码AI生态新范式,擘画智能未来新图景
  • 基于Springboot+Vue的校园设备维护报修系统(源码+lw+部署文档+讲解等)
  • 瞬维智能:以AI获客智能体重塑房产行业增长逻辑
  • 瞬维智能CEO刘哲先生受邀参加2025年火山引擎FORCE原动力大会
  • 完整教程:【华为云DevUI开发实战】
  • 基于Springboot+Vue的物品租赁管理系统(源码+lw+部署文档+讲解等)
  • 回收沃尔玛购物卡选对平台,京顺回收多赚的钱能再买两箱牛奶
  • 基于Springboot+Vue的乡村信息管理系统(源码+lw+部署文档+讲解等)
  • 实用指南:CentOS Stream 9入门学习教程,从入门到精通,Linux操作系统概述 —全面知识点详解(1)
  • 基于Springboot+Vue的乡镇卫生所医用物资进销存系统(源码+lw+部署文档+讲解等)
  • 基于Springboot+Vue的小型家政服务管理系统(源码+lw+部署文档+讲解等)
  • 吐血推荐专科生必用AI论文写作软件TOP9
  • 基于Springboot+Vue的图书馆座位预约系统(源码+lw+部署文档+讲解等)