12球问题
12个球,其中一个质量和其余的不同,用一个无砝码的天平最多分3次称出。以前考虑过,但好像最终没得出详细结论,这次再想了一下,大致如下解法:
任取8个,对等称
if 平衡
异常发生在其余4个,取其中2个置左和2个正常的比较
if 平衡
未取出的2个任取1个和正常的比即可知道结果
else
取出的2个互比,即可得到结果
endif
else
不妨设左边轻,取8个中左右各3个,其中互换1对,
右边的另某1个用剩余4个(正常)中的1个换出,然后称
if 平衡
异常发生在换出者(可能重)或剩余未比较的两者(一个可重,一个可轻)
将两个“可重”的比较,如平衡,则异常为“可轻”,否则为比较的重者。
else if 左边轻
左边原始的2个互称,轻者异常
else /* 右边轻,反转 */
互换对中任取一个和正常者互称,即可找出异常
end if
end if
I have just received from dede an implenentation with some insignifcant difference, which implies that the problem has multiple solutions. We do appreciate the work he finished in python:
# vim: set sts=4 ts=4 sw=4 et:
# twlvball.py: solves the twelve balls problem.
import sys
import operator
class Ball():
def __init__(self, num, w):
self.num = num
self.weight = w
def main():
print "This program is fragile. Try not to enter wrong arguments."
sys.stdout.write("ball number[0-11]: ")
num = int(sys.stdin.readline().rstrip())
sys.stdout.write("weight[h/l]: ")
w = sys.stdin.readline()
test(num, w)
def test(num, w):
balls = []
for i in range(12):
balls.append(Ball(i, 100))
balls[num].weight = (150 if w == "h" else 50)
print solve(balls)
def solve(balls):
# weigh 4 left, 4 right and 4 free.
res0 = weigh(balls[0:4], balls[4:8])
if res0 == 0:
# in 4 free: 8, 9, 10, 11; weigh 1 left, 1 right and 2 free.
if weigh(balls[8:9], balls[9:10]) != 0:
# in 2 weighed; weigh 1 good left and 1 unsure right.
if weigh(balls[0:1], balls[8:9]) != 0:
return 8
else:
return 9
else:
# in 2 free; weigh 1 good left and 1 unsure right.
if weigh(balls[0:1], balls[10:11]) != 0:
return 10
else:
return 11
else:
# in 8 weighed; do a 5-3 split and within the 5, do a 2-1 swap.
# for example, we take 3 from the left and 2 from the right.
# the rest 3 are removed.
# and swap 2 of the left to the right and 1 of the right to the left.
# and then fill each side with good ones.
# the idea is: make them as divided as much, and swapping 3 balls is
# better than swapping 2.
# make the number balanced using good ones.
# [0:1]: one of the left.
# [5:6]: one of the right swapped to the left.
# and plus a good one.
left = concat(balls[0:1], balls[5:6], balls[8:9])
# [4:5]: one of the right.
# [1:3]: two of the left swapped to the right.
right = concat(balls[4:5], balls[1:3])
res1 = weigh(left, right)
if res1 == 0:
# in the rest 3 balls: 3, 6, 7; n6 and n7 were on the right and n3
# were on the left originally in the first weighing.
# take 1 from right to left, and leave 1 from left still left, and
# weigh them against 2 good balls.
# [3:4]: originally left.
# [6:7]: originally right.
left = concat(balls[3:4], balls[6:7])
# take two good balls
right = balls[0:2]
res2 = weigh(left, right)
if res2 == 0:
# ah, the one that is not weighed.
return 7
elif res2 != res0:
# the one moved from right to left
return 6
else:
# the one stayed on the left
return 3
elif res1 == res0:
# among those not swapped: 0, 4; take a good with an unsure.
if weigh(balls[0:1], balls[1:2]) == 0:
# the rest
return 4
else:
return 0
else:
# among the swapped: 1, 2, 5
# leave n5 on the right, and move n1 to the right.
# have 2 good on the left.
left = concat(balls[0:1], balls[3:4])
right = concat(balls[1:2], balls[5:6])
res2 = weigh(left, right)
if res2 == 0:
# the one that is not weighed.
return 2
elif res2 != res0:
# the one moved from left to right
return 1
else:
# the one stayed on the right
return 5
def concat(*lists):
return reduce(operator.add, lists)
def weigh(a, b):
return sum([x.weight for x in a]) - sum([x.weight for x in b])
main()
reference: http://blog.csdn.net/r_mosaic/archive/2007/08/27/1760377.aspx