有70枚硬币,其中有一枚假硬币。需要在最小称量数量下检测假币。你只有一个秤,你知道假币很轻。
我不确定下面的问题模拟是对还是错,即在数组中表示它并按照我在代码中进行的比较。我试图用一个包含所有一个数组的数组来模拟它,除了一个被认为是伪币的零。以下是我的代码。如果我弄错了,请告诉我。
如果有人可以证明/解释为什么3路除法在简单数学中更好,那将会非常有用。
以下代码的伪代码:
INPUT : integer n
if n = 1 then
the coin is fake
else
divide the coins into piles of A = ceiling(n/3), B = ceiling(n/3),
and C = n-2*ceiling(n/3)
weigh A and B
if the scale balances then
iterate with C
else
iterate with the lighter of A and B
代码:
import random
def getmin(data, start, end, total_items):
if total_items == 1:
#for sure we have a fake coin
return (0, start)
elif total_items == 2:
if data[start] > data[end]:
return (1, end)
elif data[start] < data[end]:
return (1, start)
else:
partition = total_items/3
a_weight = sum(data[start:start+partition])
b_weight = sum(data[start+partition:start+2*partition])
c_weight = sum(data[start+2*partition:end])
if a_weight == b_weight:
result = getmin(data, start+2*partition, end, end-(start+2*partition))
return (1+result[0], result[1])
else:
if a_weight > b_weight:
result = getmin(data, start+partition, start+2*partition, partition)
return (1+result[0], result[1])
else:
result = getmin(data, start, start+partition, partition)
return (1+result[0], result[1])
n = int(raw_input())
data = [1]*n
data[random.randint(0, n-1)] = 0
total_weighing, position = getmin(data, 0, len(data), len(data))
print(total_weighing, position)
答案 0 :(得分:2)
此算法的复杂性为 O(log 3 N),因为在每次迭代中将问题大小减少到1/3。复杂性 O(log 3 (n)) == O(log 2 (n)) = = O(log 10 (n))因此,如果将问题大小除以3或10,则无关紧要。 only 更好的复杂性是 O(1),这意味着无论问题的大小,您都可以在固定数量的操作中找到假币,这是不太可能的。
请注意,在此算法中,我们假设我们可以在O(1)中找到一系列元素的总和,否则算法的复杂度为O(n)。
答案 1 :(得分:1)
你问“为什么三向分割在简单数学方面更好”。比什么更好?在这个问题中,它是最好的解决方案,因为它在最少的称重中实现了答案。平凡秤的属性产生三个基本结果:左侧较重,右侧较重,且重量相等。这是一个三向决策,因此信息理论产生的最佳算法是在每个阶段将对象分成三个(如果你能实际实现它)。
你需要4次称重才能获得28-81个硬币。
幸运的是,您的问题可以进行详尽的测试。 上面的代码执行一次随机测试。这对初学者来说没问题,但只有70个案例要检查,我建议你全部尝试。将主程序包裹在范围内的循环中(70),如下所示:
n = 70
for bad_coin in range(70):
data = [1]*n
data[bad_coin] = 0
total_weighing, position = getmin(data, 0, n, n)
print ("trial", bad_coin)
if total_weighing != 4:
print ("Wrong number of weighings:", total_weighing)
if position != bad_coin:
print ("Wrong ID:", position)
这将很快显示您的程序中所分配的70个硬币的任何错误。
BTW,如果您对该功能感到满意,请将 if 语句替换为断言。