CCF-GESP六级C++真题精讲:用‘01背包’思路搞定‘小杨买饮料’(附完整代码)
CCF-GESP六级C真题精讲用‘01背包’思路搞定‘小杨买饮料’附完整代码当算法竞赛选手第一次看到小杨买饮料这道题时往往会陷入两种极端要么觉得这不过是个简单的贪心选择问题要么被题目中总容量不低于L的条件吓得手足无措。实际上这道来自CCF-GESP六级考试的真题完美诠释了动态规划在实际问题中的巧妙应用——它表面上是个购物问题骨子里却是个标准的01背包变种。1. 题目本质与算法选择题目描述看似简单商店有N种饮料每种有价格和容量要求购买总容量≥L的前提下花费最少且每种饮料最多买一瓶。新手容易犯的错误是直接按性价比每毫升价格排序后贪心选择但样例1已经证明这种思路的错误——最优解9元对应的方案(2,4,3元)并非性价比最高的组合。关键突破点在于识别出三个核心特征离散决策每种饮料只有买/不买两种选择累积效应总容量是各饮料容量的叠加最优子结构当前决策影响后续状态这三点正是动态规划特别是01背包的典型适用场景。但与经典背包问题不同的是特征经典01背包小杨买饮料限制条件容量≤上限容量≥下限目标价值最大化花费最小化边界处理超容即无效超容仍有效2. 动态规划状态设计解决这个问题的核心是设计合适的状态表示。我们定义dp[j]获得至少j毫升饮料的最小花费初始状态dp[0] 00毫升不需要花钱其余设为无穷大表示不可达状态转移方程需要考虑题目允许超额满足的特殊条件dp[j] min(dp[j], dp[max(j - l, 0)] c);其中max(j - l, 0)的处理是关键——当当前饮料容量l已经满足剩余需求j时我们直接从dp[0]转移而来。实现细节注意点内循环需要倒序枚举j避免同一饮料被多次选择最终解是dp[L]若仍为初始值则输出无解数组大小应设为L1而非饮料总容量上限3. 完整代码实现与逐行解析以下是带详细注释的AC代码严格遵循CCF考试提交规范#include iostream #include algorithm using namespace std; const int INF 1e9; // 定义足够大的数代表无穷大 int main() { int N, L; cin N L; int* dp new int[L 1]; // 动态数组更灵活 fill(dp, dp L 1, INF); // C标准库填充函数 dp[0] 0; // 基础状态初始化 for (int i 0; i N; i) { int cost, volume; cin cost volume; // 逆向更新防止重复选择 for (int j L; j 0; --j) { int prev max(j - volume, 0); dp[j] min(dp[j], dp[prev] cost); } } if (dp[L] INF) { cout no solution endl; } else { cout dp[L] endl; } delete[] dp; // 释放动态数组 return 0; }关键代码段解析fill(dp, dp L 1, INF)比循环赋值更高效的初始化方式prev max(j - volume, 0)处理超额满足的核心逻辑j--的遍历顺序确保每种饮料只被考虑一次动态数组管理适应不同规模的L值4. 算法复杂度与优化空间该解法的时间复杂度为O(N*L)空间复杂度O(L)。对于GESP考试的数据规模通常N,L≤1000完全足够。但在实际竞赛中可以考虑以下优化方向滚动数组技巧vectorint dp(L 1, INF); dp[0] 0; for (auto drink : drinks) { for (int j L; j 0; --j) { int prev max(j - drink.vol, 0); dp[j] min(dp[j], dp[prev] drink.cost); } }常见错误排查表错误现象可能原因解决方法输出结果偏大正序更新导致重复选择改为逆序更新部分样例WA未处理超额满足条件添加max(j-l,0)处理内存超限数组开得过大精确计算L1空间时间超限使用vector未reserve预分配内存5. 同类问题拓展与思维训练掌握这个模型后可以解决一系列变种问题恰好满足版要求总容量严格等于L修改初始化时只设dp[0]0转移时去掉max处理多重选择版每种饮料可买多瓶解法将内循环改为正序转化为完全背包问题双限制条件同时限制总容量和总瓶数状态设计dp[j][k]表示j容量k瓶时的最小花费推荐练习题目LeetCode 416分割等和子集POJ 3624经典01背包AtCoder DP Contest D变种背包在实际编程竞赛中动态规划的难点往往不在于写出状态方程而在于准确识别问题背后的模型。建议通过以下步骤训练将问题描述中的关键参数提取为物品和容量明确决策选项选/不选选多少次确定目标是最小化还是最大化处理特殊边界条件如本题的超额满足