假设您在N
个开关的房间,并且在下一个房间里有一个灯泡。只有当某些指定的开关全部打开时,灯泡才会发光。
集
switches
=所有开关的集合。 |switches| = N
。 required
=需要打开以使灯泡发光的开关。 不需要的开关并不重要。
只有进入下一个房间,才能检查灯泡是否发光。您可以打开或关闭某些开关,转到下一个房间检查灯泡,然后重复此过程。让我们称之为ATTEMPT。
假设在最坏情况下有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
,您能否提供正式证明?
答案 0 :(得分:11)
证明最坏情况需要至少N次尝试
如果有N个开关,则可能有2 ^ N个可能的'必需'组,因为每个开关可以进入或离开'必需'组。
要区分2 ^ N个可能的集合,您可以考虑它,因为我们需要通过摆弄交换机来获得至少N位的信息。如果没有,那么有可能存在多于1套,它们都能适合我们目前所知的信息。
让我们假设有8种可能的配置(N = 3),我们可以选择配置子集并查询“required”配置是否在所选子集中。执行此操作的最佳方法类似于二进制搜索,实现log(2 ^ N)的复杂性,这只是N次尝试。如果我们使用少于3次尝试,我们将留下至少2种配置,我们无法确定哪种配置是正确的,因为每次尝试都将消除一半可能的配置。
回到最初的问题,让我们假设我们到目前为止使用K次尝试K< N.由于每次尝试都会提供1位信息(是的,它亮起/不亮,它没有点亮),每次尝试都可以消除一半可能的配置,我们将留下2 ^(NK)可能的配置K尝试。
要获得“必需”集合的仅1个不同的可能配置,我们将需要K = N,这将给出2 ^(N-N)= 2 ^ 0 = 1可能的配置。
这给了我们这个问题的下限,因为每次尝试都会提供1位信息(是的,它点亮/不亮,它不会点亮)。因此,我们至少需要N次尝试。
使用不超过N次尝试的可能解决方案
由于“非必需开关无关紧要”,如果我正确解释它,则意味着如果“必需”组外的开关打开,除了“必需”组中的开关外,灯光将会亮起还在上。由于我们有N次尝试使用(并且仍然使其最佳),我们可以使用以下解决方案: 对于每个开关(按顺序),打开除此开关之外的所有其他开关。 检查灯是否已关闭。如果关闭,唯一保持关闭的开关将处于“必需”设置中。
此解决方案将使用N次尝试(即使在更糟糕的情况下),它是最佳解决方案之一(如前所述)。
答案 1 :(得分:2)
假设在WORST CASE中有N个开关,找出所需开关集所需的最小尝试次数(使用优化策略)是什么?
蛮力的方式,检查所有可能的开关组合,直到灯亮,这将是O(2^N)
(虽然我们可能会很幸运,并在我们第一次尝试后打开灯)。
通过更优化的搜索,可以在最差O(N)
次尝试中找到所需的开关集。以下是始终O(N)
的一种方式:
翻开所有N
开关:我们知道灯将亮起。
关闭开关1。如果指示灯熄灭,则需要开关1,因此请将其重新打开。如果指示灯亮起,请关闭开关1,因为 这不是必需的。 (使用了一次尝试)。
关闭开关2:如果指示灯熄灭,则需要开关2,然后重新打开。如果灯仍然亮着,请关闭开关2,因为它不是必需的。 (两次尝试使用)。
对其余每个开关重复此检查。 (N
尝试使用过。)
N
后,我们将在开启位置留下所需开关的集合。正如其他答案/评论中所述,也可以在最佳情况O(log(N))
和最差情况O(N)
找到所需的开关集:
翻开所有N
开关:我们知道灯将亮起。
关闭第一个N/2
开关。在灯保持亮起时,不需要这些开关,因此我们可以关闭开关。移至仍然打开的N/2
个开关集,然后重复此步骤......
如果灯熄灭,则至少需要其中一个N/2
开关:重新打开开关,将组分成两半并重复上一步......
此算法是最差情况O(N)
,因为我们可能需要单独检查每个交换机(例如,如果有10个交换机且所需配置为0101010101)。
答案 2 :(得分:-1)
假设我们需要尝试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。
编辑:我认为这解决了一个稍微不同的问题,即某些开关上的灯需要关闭以使灯亮起。