算法设计 - 用最少的测试人员识别酒窖中的单瓶

时间:2013-01-18 19:52:42

标签: algorithm

这是算法类中的额外功劳。问题陈述

  一位国王有一个N瓶酒窖,一瓶已经中毒       毒药大约需要一个月的时间。国王想要确切的瓶子       在几个月的时间内使用最少的测试人员确定。

我的解决方案是

  • N瓶分成M批并使用“M测试员

    • 第一位测试者尝试第一批和最后一批

    • 第二个测试者尝试第一批和第二批。

    • 第三位测试者尝试第二批和第三批。

    • 继续M批次,测试人员重叠。

  • 当两位品尝了受污染葡萄酒的测试人员生病时,已确定该批次。 M-2测试人员从污染的地段中分别品尝了一瓶,第三个生病的测试人员识别出受污染的瓶子。

然而,这种算法需要分配两倍的工作时间:一个月来识别受污染的批次,第二个月来识别受污染的瓶子。有更高效的算法吗?

4 个答案:

答案 0 :(得分:7)

我们可以使用非常简洁的算法与log2(N)测试人员一起完成。

让我用一个简单的例子来演示它。假设N = 1000

如果我们将瓶子0标记为999,那么每个瓶子都可以用从00000000000十进制)到{{1}的唯一二进制数来表示(111100111十进制)。

索赔:我们只需要10名测试人员就可以找到中毒的瓶子。注意:999

算法:对于log2(N) = log2(1000) = 10瓶,我们首先获得M的10位二进制表示。如果二进制数的M位为i,我们让1测试人员从瓶中喝酒。注意:i

考虑一个例子,我们让0 < M <1000, 0 < i <101st4th测试人员死了,其他测试人员在一个月后还活着。我们得出结论,9th瓶是中毒瓶,因为289th是十进制数0100100001的二进制表示。

为什么289测试人员足以识别10瓶中的中毒者?

因为最终每个1000测试者都死了或活着,我们可以总共有10个组合,每个组合可用于唯一地识别一个瓶子中毒1024瓶。

答案 1 :(得分:5)

这是一个经典的谜题,所以我不想立即给出答案,但这里有一个暗示:假设你将酒瓶分成两组,每组包含一半瓶子,然后有一个人测试每一半。那会让你有办法缩小哪一瓶被中毒到一半的瓶子。

所以问题是 - 有没有办法提出许多不同的方法将酒瓶分成两半并同时运行上述方法?作为提示,请考虑N的二进制表示。

希望这有帮助!

答案 2 :(得分:0)

这是我的建议。这基本上来自并行算法。

  1. 将瓶子分成n / log2(n)。将每个部门称为子问题来解决。
  2. 在步骤1中将每个log2(n)测试人员分配给每个子问题。
  3. 最后说一个测试仪死了,说我们还有log2(n)瓶和log2(n) - 1个测试者。
  4. 每个测试者测试一瓶。剩下一瓶了。
  5. 如果没有测试仪死亡(或者至少在最初几天出现症状......那是我的假设)那么我们就知道罪魁祸首就是留下的瓶子。
  6. 如果任何一个测试仪死亡(或至少显示疾病),那么我们知道该测试仪测试的瓶子是罪魁祸首。
  7. 这需要log2(n)+ 1个月。由于1是常数,我们可以忽略它,并且可以说它是O(log2(n))。

答案 3 :(得分:0)

提供一个例子:

将每个瓶子从1标记为n,并将每个瓶子视为二进制数字。 例如11瓶

00000001 
00000010 
00000011 
00000100 
00000101 
00000110 
00000111
00001000 
00001001 
00001010 
00001011

现在,从右到左,首先从每个最小位设置为“1”的瓶子中取出一滴并放入第一个杯子中。 然后从第2位设置为“1”的每个瓶子中取出一滴并放入第二个杯子中 通过最高位以类似的方式继续。总共我们需要4杯和4个品尝者。

taster4 taster3 taster2 tester1
cup4     cup3    cup2     cup1

我们现在将品尝者映射到杯子并将杯子映射到位,因此将品尝者映射到位 指挥品尝者喝酒。在一个月内,你的一些品尝者将会死亡。 例如taster3和taster1变得死了 然后将相应的位设置为1,将所有其他位设置为0.生成的二进制数 00000101将识别有毒的瓶子。 品尝者的数量f(n)=(int)(logn)+1,所以f(n)是O(logn)