You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅用$20和$50纸币的ATM取现最少纸币数正确算法问询

解决仅用$20和$50纸币凑目标金额的最少张数问题

贪心算法在这种纸币组合下不适用——它只优先选择大面额,会出现无法凑齐目标金额或得到非最优解的情况,比如你给出的110和130的例子:贪心算法要么留下无法用20凑的余数,要么得到的总张数不是最少的。

下面是两种无需大量if语句的合理解法:

方法一:遍历验证法

从最多的50美元纸币数量开始向下遍历,找到第一个能让剩余金额被20整除的组合——因为总张数随50纸币数量的增加而减少,第一个符合条件的组合就是最优解。

def calculate_min_notes(amount):
    # 过滤无效金额:非10的倍数或小于20的金额
    if amount % 10 != 0 or amount < 20:
        return None
    
    max_fifties = amount // 50
    # 从最多的50纸币开始试,直到0
    for fifties in range(max_fifties, -1, -1):
        remainder = amount - fifties * 50
        if remainder % 20 == 0:
            twenties = remainder // 20
            return {50: fifties, 20: twenties}
    
    # 无法凑出的情况(如30美元)
    return None

测试示例:

print(calculate_min_notes(110))  # 输出 {50: 1, 20: 3}
print(calculate_min_notes(130))  # 输出 {50: 1, 20: 4}
print(calculate_min_notes(100))  # 输出 {50: 2, 20: 0}(最优解)
print(calculate_min_notes(70))   # 输出 {50: 1, 20: 1}(最优解)

方法二:数学推导法

通过数学公式直接计算最优解,无需遍历,效率更高:
设50美元数量为x,20美元数量为y,目标金额amount可转化为:
50x + 20y = amount → 两边除以10得 5x + 2y = total(total = amount // 10)
总张数x + y = (total - 3x)/2,要最小化总张数,需最大化x,且total -5x需为非负偶数(因为2y必须是偶数)。

def calculate_min_notes_math(amount):
    if amount % 10 != 0 or amount < 20:
        return None
    
    total = amount // 10
    max_fifties = total // 5
    fifties = max_fifties
    
    # 确保total和x同奇偶(因为5x的奇偶性等于x的奇偶性)
    if total % 2 != fifties % 2:
        fifties -= 1
        # 若减1后仍不满足,再减1(最多减2次,奇偶性必然匹配)
        if fifties >=0 and total %2 != fifties%2:
            fifties -=1
    
    # 检查是否为有效数量
    if fifties <0 or (total - 5*fifties) <0:
        return None
    
    twenties = (total -5*fifties) //2
    return {50: fifties, 20: twenties}

两种方法都能正确处理所有有效金额,逻辑简洁,避免了冗余的if判断。

内容的提问来源于stack exchange,提问作者AndreFeijo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:54:58