【问题标题】:Fallacy in Logic for Project Euler's Challenge 31欧拉计划挑战的逻辑谬误 31
【发布时间】:2012-08-24 20:07:40
【问题描述】:

也许我误读了这个问题。对于那些不熟悉Project Euler's Problem 31 的人,这里有问题:

调查英国货币面额的组合。

在英格兰,货币由英镑、英镑和便士组成,一般流通的硬币有八种:

1p、2p、5p、10p、20p、50p、1 英镑 (100p) 和 2 英镑 (200p)。

可以通过以下方式赚取 2 英镑:

1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p

使用任意数量的硬币可以通过多少种不同的方式制作 2 英镑?

我明白这怎么可能是一个动态编程问题,但我忍不住走捷径:

为了解决这个问题,我分解了使用 1p、1p 和 2p 以及 1p、2p 和 5p 硬币可以制作 1 到 6 便士的方法。

仅使用一美分硬币

  1. 1 个组合
    • 1p
  2. 1 个组合
    • 2×1p
  3. 1 个组合
    • 3×1p
  4. 1 个组合
    • 4×1p
  5. 1 个组合
    • 5×1p
  6. 1 个组合
    • 6×1p

仅使用一便士和两便士硬币

  1. 1 个组合
    • 1p
  2. 2 种组合
    • 2p
    • 2×1p
  3. 2 种组合
    • 2p + 1p
    • 3×1p
  4. 3 种组合
    • 2×2p
    • 2p + 2×1p
    • 4×1p
  5. 3 种组合
    • 2×2p + 1p
    • 2p + 3×1p
    • 5×1p
  6. 4 种组合
    • 3×2p
    • 2×2p + 2×1p
    • 2p + 4×2p
    • 6×2p

仅使用一便士、两便士和五便士硬币

  1. 1 个组合
    • 1p
  2. 2 种组合
    • 2p
    • 2×1p
  3. 2 种组合
    • 2p + 1p
    • 3×1p
  4. 3 种组合
    • 2×2p
    • 2p + 2×1p
    • 4×1p
  5. 4 种组合
    • 5p
    • 2×2p + 1p
    • 2p + 3×1p
    • 5×1p
  6. 5 种组合
    • 5p + 1p
    • 3×2p
    • 2×2p + 2×1p
    • 2p + 4×2p
    • 6×2p

我注意到这种疯狂是有规律的。显然,最多只有一种方法可以仅用一种硬币获得所需的“余额”。对于这个问题的情况,没有必要考虑一分钱。因此,仅使用一美分硬币,只有一种方法可以获得任何非负余额。请注意,只有一种方法可以获得零余额:没有硬币。

快速浏览了一下,我注意到第二个示例中的模式。可能组合的数量等于 n / 2 加 1 的商,其中 n 是任何非负整数。在 Python(我编写解决方案时使用的语言)中,如下所示:

n // 2 + 1

我注意到+ 1 正在为特定“目标余额”添加上一个示例的结果。巧合?可能是。但看了第三个例子后,我很快注意到可能的组合数量如下:

n // 5 + n // 2 + 1

我实现了这个模式,它将占所有八个硬币:

n // 200 + n // 100 + n // 50 + n // 20 + n // 10 + n // 5 + n // 2 + 1

n 设置为 200,我推断答案是 178。这个数字对我来说是有意义的,不过,我不会自己编写所有可能的组合。然而,Project Euler 指出这是不正确的。

我在网上查到正确的解法是73682。

所以我想问你,仍在阅读的 Stack Overflow 用户,我的推理中的谬误在哪里?

【问题讨论】:

  • 我不确定我是否可以解释哪里出了问题,但你的公式不适用于 n >= 7。
  • @Blckknght,你问的很有趣。不,当n 为 7 时,输出为 5。但是,我发现答案实际上是 6。也许我的逻辑只是巧合地适用于给定的示例?我也刚刚确认它不适用于 8、9 或 10。

标签: python algorithm dynamic-programming combinatorics


【解决方案1】:

仅使用 [1, 2, 5] 制作 10p 的正确组合数是 10,而您的解决方案给出 10 / 5 + 10 / 2 + 1 = 2 + 5 + 1 = 8。显然你的假设是不正确的.

错误在于,您只是在尝试一些案例,并假设适用于少数小案例的方法适用于所有案例,而没有任何证据。

【讨论】:

  • 刚刚在上面确认。正确的解决方案对我来说仍然听起来有点牵强。 :/我想这不会是一个棘手的问题,不过,如果解决方案是如此之小。回到绘图板。
  • @TylerCrompton:解决方案确实是动态规划,如果你以前解决过 DP 问题,这并不是特别难。如果您遇到困难,请告诉我。
  • 我已经解决了相当多的 DP 问题,所以我应该能够处理它。回顾我的“解决方案”,我不知道为什么我认为这是正确的。 *耸肩*
  • 这就是为什么演绎逻辑(相对于归纳逻辑)在数学中如此重要:)
  • 动态编程并不是这里唯一的解决方案(尽管它可以说是最好的)。递归解决方案在这里也可以正常工作。