这是算法类中的额外功劳。问题陈述
一位国王有一个N瓶酒窖,一瓶已经中毒 毒药大约需要一个月的时间。国王想要确切的瓶子 在几个月的时间内使用最少的测试人员确定。
我的解决方案是
将N
瓶分成M
批并使用“M测试员
第一位测试者尝试第一批和最后一批
第二个测试者尝试第一批和第二批。
第三位测试者尝试第二批和第三批。
继续M批次,测试人员重叠。
当两位品尝了受污染葡萄酒的测试人员生病时,已确定该批次。 M-2
测试人员从污染的地段中分别品尝了一瓶,第三个生病的测试人员识别出受污染的瓶子。
然而,这种算法需要分配两倍的工作时间:一个月来识别受污染的批次,第二个月来识别受污染的瓶子。有更高效的算法吗?
答案 0 :(得分:7)
我们可以使用非常简洁的算法与log2(N)
测试人员一起完成。
让我用一个简单的例子来演示它。假设N = 1000
。
如果我们将瓶子0
标记为999
,那么每个瓶子都可以用从0000000000
(0
十进制)到{{1}的唯一二进制数来表示(111100111
十进制)。
索赔:我们只需要10名测试人员就可以找到中毒的瓶子。注意:999
。
算法:对于log2(N) = log2(1000) = 10
瓶,我们首先获得M
的10位二进制表示。如果二进制数的M
位为i
,我们让1
测试人员从瓶中喝酒。注意:i
。
考虑一个例子,我们让0 < M <1000, 0 < i <10
,1st
,4th
测试人员死了,其他测试人员在一个月后还活着。我们得出结论,9th
瓶是中毒瓶,因为289th
是十进制数0100100001
的二进制表示。
为什么289
测试人员足以识别10
瓶中的中毒者?
因为最终每个1000
测试者都死了或活着,我们可以总共有10
个组合,每个组合可用于唯一地识别一个瓶子中毒1024
瓶。
答案 1 :(得分:5)
这是一个经典的谜题,所以我不想立即给出答案,但这里有一个暗示:假设你将酒瓶分成两组,每组包含一半瓶子,然后有一个人测试每一半。那会让你有办法缩小哪一瓶被中毒到一半的瓶子。
所以问题是 - 有没有办法提出许多不同的方法将酒瓶分成两半并同时运行上述方法?作为提示,请考虑N的二进制表示。
希望这有帮助!
答案 2 :(得分:0)
这是我的建议。这基本上来自并行算法。
这需要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)