【问题标题】:The algorithm to find the required switches to turn on a light blub找到打开灯泡所需开关的算法
【发布时间】:2014-09-03 06:02:19
【问题描述】:

假设您在一个带有N 开关的房间里,而隔壁房间里有一个灯泡。只有当某些特定的开关全部打开时,灯泡才会发光。

设置

  • switches = 所有开关的集合。 |switches| = N
  • required = 需要打开才能使灯泡发光的开关。

不需要的开关无关紧要。

只有进入下一个房间才能检查灯泡是否发光。你可以打开或关闭一些开关,去隔壁房间检查灯泡,然后重复这个过程。让我们称之为一次尝试。

假设有N 开关,在最坏的情况下,找出required 开关集所需的最少尝试次数是多少(使用优化策略)?


例如,

  • switches = { 1, 2, 3 }
  • required = { 1, 2 }

让我们尝试一种简单的方法:

  • 打开{ 1, 2 },灯会发光。 (确保不需要开关 3)
  • 打开{ 1, 3 },灯不亮。 (确保需要开关 2)
  • 打开{ 2, 3 },灯不亮。 (确保需要开关 1)

因此通过 3 次尝试,我们可以确保 required = { 1, 2 }

这个问题的优化算法是什么?

worst(N) 成为考虑N 在最坏情况下切换的最小尝试。你能找到worst(N)

更新:如果你认为worst(N) = N,你能提供一个正式的证明吗?

【问题讨论】:

  • 这就像公牛和奶牛的简化版。
  • 在最坏的情况下,它们都是必需的,并且需要 N 次尝试来验证它。对?因为每次尝试都会告诉您是否需要一组开关中的至少一个元素。所以你不能一次将你知道的数字增加超过 1 个。
  • 能否请您澄清一下:非必需的开关是忽略,还是会关闭灯泡?例如。如果我们打开每个开关,包括不需要的开关,灯泡会亮吗?如果是这样,这可以为二进制搜索方法奠定基础。
  • @PelitMamani。不需要的开关被忽略。抱歉描述不清楚
  • @miaout17 只有在所需开关的数量已知并且它们是1 or N - 1 时才会有 log(N) 解决方案。

标签: algorithm math


【解决方案1】:

证明最坏的情况需要至少 N 次尝试

如果有 N 个开关,则可以有 2^N 个可能的“必需”集,因为每个开关都可以在“必需”集之内或之外。

为了区分 2^N 个可能的集合,您可以这样想,因为我们需要通过摆弄开关来获得至少 N 位的信息。如果不是,则可能有超过 1 个集合都可以拟合我们目前所知道的信息。

假设有 8 种可能的配置 (N = 3),我们可以选择配置子集并查询“必需”配置是否在所选子集中。最好的方法是类似于二分搜索,实现 log(2^N) 的复杂性,这只是 N 次尝试。如果我们使用少于 3 次尝试,我们将留下至少 2 种配置,我们无法确定哪个是正确的,因为每次尝试都会消除一半可能的配置。

回到最初的问题,假设我们到目前为止使用了 K 次尝试,其中 K

要获得“必需”集的 1 个不同的可能配置,我们需要 K = N,这将为我们提供 2^(N-N) = 2^0 = 1 个可能的配置。

这为我们提供了这个问题的下限,因为每次尝试都会提供 1 位信息(是的,它会亮起/否,它不会亮起)。因此,我们将需要至少 N 次尝试。

尝试不超过 N 次的可能解决方案

由于“非必需开关无关紧要”,如果我解释正确,这意味着如果打开“必需”设置之外的开关,除了“必需”设置中的开关,灯会还在继续。由于我们有 N 次尝试使用(并且仍然使其最佳),我们可以使用以下解决方案: 对于每个开关(按顺序),打开除此开关之外的所有其他开关。 检查灯是否关闭。如果它被关闭,唯一保持关闭的开关将在“必需”集中。

此解决方案将使用 N 次尝试(即使在更坏的情况下),它是最佳解决方案之一(如前所述)。

【讨论】:

  • 我认为您的描述可能是正确的,但我不确定。你能用更数学的方式形式化第二段吗?感谢您抽出宝贵时间回答我的问题。
  • 感谢您的更新。我需要一些时间来考虑一下。投票赞成。
  • 已接受。解释得很好!感谢您花时间回答我:)
【解决方案2】:

假设有 N 个开关,在 WORST CASE 中,找出所需开关集合所需的最少尝试次数是多少(使用优化策略)?

蛮力的方法,检查所有可能的开关组合,直到灯亮起,这将是O(2^N)(尽管我们可能很幸运,在第一次尝试后就打开了灯)。

通过更优化的搜索,可以在最坏的情况下找到所需的开关集O(N) 尝试。这是始终为O(N) 的一种方式:

  • 打开所有N开关:我们知道灯会亮。

  • 关闭开关 1。如果灯熄灭,则需要开关 1,然后将其重新打开。如果灯一直亮着,请关闭开关 1,因为 这不是必需的。 (使用了一次尝试)。

  • 关闭开关 2:如果灯熄灭,则需要开关 2,因此将其重新打开。如果灯一直亮着,请关闭开关 2,因为它不是必需的。 (使用了两次尝试)。

  • 对剩余的每个开关重复此检查。 (N 尝试使用)。

  • N 尝试后,我们剩下的一组所需的开关处于打开位置。

正如其他答案/cmets 中所述,在最佳情况 O(log(N)) 和最坏情况 O(N) 中也可以找到所需的开关集:

  • 打开所有N 开关:我们知道灯会亮。

  • 翻转第一个N/2 关闭。在灯一直亮着的情况下,不需要这些开关,所以我们可以关闭这些开关。移动到仍然打开的N/2 开关组并重复此步骤...

  • 如果灯熄灭,则至少需要其中一个N/2 开关:重新打开开关,将设备分成两半并重复上一步...

    李>

这种算法是最坏的情况O(N),因为我们可能必须单独检查每个交换机(例如,如果有 10 个交换机并且所需的配置是 0101010101)。

【讨论】:

  • 我的意思是,所需的开关集可以在 best 案例O(1) 中找到。只打开开关1,检查灯是否亮。如果是,那么您就在那里得到了答案。如果不是,则返回线性扫描。
  • 我同意...我的回答描述了一些比打开每个可能的开关组合更优化的策略。我正在解决第一个问题(“在最坏的情况下,使用优化策略所需的最少尝试次数是多少?”)
  • 如果需要所有开关,实际最坏的情况不会是 O(N + log(N)) 吗?
  • O(N + log(N)) 等价于O(N)(因为N 支配log(N))。
【解决方案3】:

假设我们需要尝试所有可能的 N 个开关组合。我们可以将其表示为二进制数,例如 0101,并且我们要检查每个二进制数。一种天真的方法就是依次遍历每个数字:0000(全部关闭)、0001(开关 4 开启)、0010(开关 3 开启)、0011(开关 3 和 4 开启)。请注意,如何从 0001 到 0010 实际上需要两个步骤,即关闭 4 和打开 3。

一种称为Gray code 的更好算法会遍历每个数字,因此每次只切换一个数字。顺序是 0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010、1011、1001、1000。

编辑:我认为这解决了一个稍微不同的问题,即点亮某些开关需要关闭才能点亮。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    相关资源
    最近更新 更多