C++ 算法考级专栏
真题分析、矩阵探测、递归回溯与基础语法
🎨 视觉封面【贪心算法与平均值平衡杠杆原理】GESP五级 / CSP-J 题解:luogu-P17456 [GESP202609 五级] 饮品调制
CCF GESP 2026年9月认证(第十五次认证)C++ 五级试题,洛谷 P17456。本题严格遵循 CCF GESP 官方大纲规范,重点考察贪心算法与平均值平衡杠杆原理。题目逻辑严密,模型典型,是深入理解与掌握信奥核心考点的经典范例。
P17456 [luogu-P17456 [GESP202609 五级] 饮品调制]
🔗 洛谷原题传送门:P17456
题目要求
题目描述
有 种原料调制饮品,第 种原料存量 升,含糖量 克/升。选用 升()。 要求最终饮品甜度恰好为 (即 )。 求最多能调制出多少升恰到好处的饮品?若无法调制,答案为 0。
输入格式
第一行两个整数 。 接下来 行,每行两个整数 。
输出格式
一行,一个小数,保留三位小数。
输入输出样例
样例输入 #1
4 2
6 1
5 2
8 5
1 0
样例输出 #1
14.667
说明/提示
。
题目分析与解题思路
- 基准差值转换:平均甜度等于 等价于净糖分盈余为 0:
- 若 :相对贡献为 0,可以无条件全额选用所有体积;
- 若 :每升提供 的正贡献;
- 若 :每升产生 的负需求。
- 贪心选择原则(单位贡献体积最大化): 为了在正负糖分平衡的前提下最大化总体积,我们希望每提供 1 单位盈余/赤字,消耗的液体体积尽可能大! 每单位糖分所需体积为 。因此, 越小,单位效率越高!
- 执行流程:
- 正侧原料按 升序排序,负侧原料按 升序排序;
- 最大可平衡的总糖分量为 ;
- 分别在正侧与负侧按排好的贪心顺序取出能达到 的体积并累加。
完整参考代码 (C++11)
/**
* Problem: luogu-P17456
* Standard: C++11 (CCF GESP 官方大纲规范)
* Author: OneCoder
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
struct Item {
double v;
double s;
double diff; // |s - t|
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
double t;
if (!(cin >> n >> t)) {
return 0;
}
double zero_vol = 0.0;
vector<Item> pos;
vector<Item> neg;
double total_pos = 0.0;
double total_neg = 0.0;
for (int i = 0; i < n; ++i) {
double v, s;
cin >> v >> s;
if (s == t) {
zero_vol += v;
} else if (s > t) {
pos.push_back({v, s, s - t});
total_pos += v * (s - t);
} else {
neg.push_back({v, s, t - s});
total_neg += v * (t - s);
}
}
// 贪心排序:diff 越小,每单位贡献换取的体积越大
sort(pos.begin(), pos.end(), [](const Item& a, const Item& b) {
return a.diff < b.diff;
});
sort(neg.begin(), neg.end(), [](const Item& a, const Item& b) {
return a.diff < b.diff;
});
double balance_w = min(total_pos, total_neg);
if (balance_w == 0.0 && zero_vol == 0.0) {
cout << "0.000\n";
return 0;
}
double ans_vol = zero_vol;
// 贪心满足正侧 balance_w
double need_pos = balance_w;
for (const auto& item : pos) {
if (need_pos <= 0) break;
double max_give = item.v * item.diff;
if (need_pos >= max_give) {
ans_vol += item.v;
need_pos -= max_give;
} else {
ans_vol += need_pos / item.diff;
need_pos = 0;
}
}
// 贪心满足负侧 balance_w
double need_neg = balance_w;
for (const auto& item : neg) {
if (need_neg <= 0) break;
double max_give = item.v * item.diff;
if (need_neg >= max_give) {
ans_vol += item.v;
need_neg -= max_give;
} else {
ans_vol += need_neg / item.diff;
need_neg = 0;
}
}
cout << fixed << setprecision(3) << ans_vol << "\n";
return 0;
}
考点归纳与备考建议
- 考纲匹配度:严格对标 CCF GESP 五级考纲重点,绝不超纲,注重基础算法与逻辑建模规范;
- 规范防范:所有代码严格以 C++11 标准编译运行,针对整数溢出、边界判断、空状态均做了详尽严整的防御性处理。
所有代码开源上传至 GitHub:yummy-code 仓库 · GESP 专题站:GESP WIKI
欢迎加入:C++ GESP/CSP 考级答疑群(688906745) 与 Java/Python交流群(982860385),点击可直接加群。
猜你想读 · 相关文章推荐
【初等数论·欧拉线性筛与素数拆分】GESP五级 / CSP-J 题解:luogu-P17455 [GESP202609 五级] 哥德巴赫猜想
CCF GESP 2026年9月认证(第十五次认证)C++ 五级试题,洛谷 P17455。本题严格遵循 CCF GESP 官方大纲规范,重点考察初等数论·欧拉线性筛与素数拆分。题目逻辑严密,模型典型,是深入理解与掌握信奥核心考点的经典范例。
【GESP】C++ 五级真题解析,[2025年12月,第十二次认证]第二题-相等序列 luogu-p14918
GESP C++ 2025年12月,五级真题第二题,考察数论与贪心算法思想,对考试来说有一定难度。题目难度⭐⭐⭐☆☆。洛谷难度等级普及/提高−。
【树形结构DFS与子树平衡度极小化】GESP六级 / CSP-J 题解:luogu-P17458 [GESP202609 六级] 分树规划
CCF GESP 2026年9月认证(第十五次认证)C++ 六级试题,洛谷 P17458。本题严格遵循 CCF GESP 官方大纲规范,重点考察树形结构DFS与子树平衡度极小化。题目逻辑严密,模型典型,是深入理解与掌握信奥核心考点的经典范例。
OneCoder (lihongzheshuai)
一个中年人的自留地,记录学习 C++、GESP/NOI、Java、Python 与算法架构的心得体会。本站唯一网址:coderli.com