Codeforces 24B是贪心算法在找零问题中的经典应用案例,题目要求用指定面额(如1、5、10、25、50等)的硬币对给定金额找零,目标是使用最少硬币数,解题核心采用贪心策略:优先选择当前更大面额硬币,尽可能多地使用,再对剩余金额重复该过程直至为零,该策略有效源于面额组合满足贪心算法的两大性质——贪心选择性质(局部更优导向全局更优)和更优子结构(子问题更优解构成原问题更优解),这道题直观展现了贪心算法在资源分配类问题中的高效应用,是理解贪心思想的典型范例。
背景与描述
Codeforces 24B是一道聚焦贪心策略的经典编程题,核心考察如何通过局部更优选择达成全局更优解,题目大意如下:
给定需要找零的金额 n(n 为10的整数倍),以及 k 种不同面额的纸币(每种面额均为10的倍数且互不重复),要求使用这些纸币组成金额 n,使得所用纸币的数量最少。
问题分析
要使纸币数量最少,直观思路是优先选择面额更大的纸币——这是贪心算法的典型应用场景,因为面额越大,所需张数越少,每次选择当前更大面额的纸币,直到凑够目标金额,即可得到更优解。
需注意的关键点:
- 所有数值均为10的倍数,可除以10简化计算(避免大数字操作,降低出错概率);
- 纸币面额需按降序排列,方便从大到小选择;
- 对每个面额,尽可能多用(直到剩余金额小于该面额),再转向下一个较小面额。
算法步骤
- 简化数值:将
n和所有面额除以10; - 排序面额:将面额数组按降序排列;
- 贪心选择:遍历每个面额,计算最多可用张数,累加至总张数,并更新剩余金额;
- 提前终止:若剩余金额为0,直接结束循环(无需继续遍历)。
代码实现(Python)
n = int(input())
k = int(input())
denoms = list(map(int, input().split()))
# 简化计算:所有数值除以10
n //= 10
denoms = [d // 10 for d in denoms]
# 按面额降序排列
denoms.sort(reverse=True)
count = 0
remaining = n
for d in denoms:
if remaining <= 0:
break
# 当前面额最多可用张数
cnt = remaining // d
count += cnt
remaining -= cnt * d
print(count)
贪心策略的正确性
为什么贪心在这里有效?因为纸币面额满足贪心选择性质:每次选更大面额不会影响后续更优性,用50、20、10凑100元,优先选50(2张)比选20(5张)更优,且不会导致后续无法凑够金额。
注意事项
- 输入面额可能未排序,需手动降序排列;
- 确保所有输入符合题目要求(面额为10的倍数);
- 剩余金额为0时提前终止,提升效率。
这道题通过简单的贪心策略即可高效解决,时间复杂度为 O(k log k)(排序时间),空间复杂度为 O(k),是初学者理解贪心算法的理想入门题。


