Codeforces 24B,贪心算法在找零问题中的经典应用(CF24BD/N7-DY发布)

minyu 4周前 (05-14) 综合 298 0
Codeforces 24B是贪心算法在找零问题中的经典应用案例,题目要求用指定面额(如1、5、10、25、50等)的硬币对给定金额找零,目标是使用最少硬币数,解题核心采用贪心策略:优先选择当前更大面额硬币,尽可能多地使用,再对剩余金额重复该过程直至为零,该策略有效源于面额组合满足贪心算法的两大性质——贪心选择性质(局部更优导向全局更优)和更优子结构(子问题更优解构成原问题更优解),这道题直观展现了贪心算法在资源分配类问题中的高效应用,是理解贪心思想的典型范例。

背景与描述
Codeforces 24B是一道聚焦贪心策略的经典编程题,核心考察如何通过局部更优选择达成全局更优解,题目大意如下:
给定需要找零的金额 nn 为10的整数倍),以及 k 种不同面额的纸币(每种面额均为10的倍数且互不重复),要求使用这些纸币组成金额 n,使得所用纸币的数量最少。

问题分析

要使纸币数量最少,直观思路是优先选择面额更大的纸币——这是贪心算法的典型应用场景,因为面额越大,所需张数越少,每次选择当前更大面额的纸币,直到凑够目标金额,即可得到更优解。

Codeforces 24B,贪心算法在找零问题中的经典应用(CF24BD/N7-DY发布)

需注意的关键点:

  1. 所有数值均为10的倍数,可除以10简化计算(避免大数字操作,降低出错概率);
  2. 纸币面额需按降序排列,方便从大到小选择;
  3. 对每个面额,尽可能多用(直到剩余金额小于该面额),再转向下一个较小面额。

算法步骤

  1. 简化数值:将 n 和所有面额除以10;
  2. 排序面额:将面额数组按降序排列;
  3. 贪心选择:遍历每个面额,计算最多可用张数,累加至总张数,并更新剩余金额;
  4. 提前终止:若剩余金额为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),是初学者理解贪心算法的理想入门题。