彻底解决“天平秤次品”问题

本文详细探讨了“天平秤次品”问题的两种类型:A类(次品比正品重)和B类(未知次品与正品的重量关系)。通过实例解析和决策树分析,展示了如何在不同情况下通过最少次数的称量找到次品。对于B类问题,重点讨论了从13个物品出发的解决方案,引入十字图和三元组的概念,简化了问题的表示和推理,并推导出在有额外正品情况下,n次称量最多可解决23n+1个物品的B类问题。
摘要由CSDN通过智能技术生成

前言

    2025年的ACM区域赛北京站上,前辈率先独自AC了一道签到题。比赛后我问前辈是什么题目,前辈说是天平称次品的问题。哦那没事了,确实是道水题。但是我看了一眼题目发现,题目说到,并不清楚次品和正品的轻重关系,这咋做啊?再看了一眼前辈的代码,核心的公式是 x = ⌈ log ⁡ 3 ( 2 n ) ⌉ x=\lceil \log_3(2n) \rceil x=log3(2n) 。WTF?我回去认真思考了一下,发现前辈的答案确实是对的。

天平称次品问题其实有两类:
A:n个物品里有1个次品,并且次品比正品重,问至多需要称多少次?
B:n个物品里有1个次品,但不知道次品和正品谁更重,问至多需要称多少次?

    对于A类问题十分简单,假如是9个物品,那么就拿出6个放在天平的左右侧(记作 3 v 3 ∼ 3 3v3\sim3 3v33,最后的3表示剩下3个没有称)。如果天平倒向左边,那么次品就在左边3个里;倒向右边,就在右边3个里;水平的话,次品则是在剩下的3个里。无论哪种情况都是变成了3个物品里有1个次品,然后依样画葫芦进行 1 v 1 ∼ 1 1v1\sim1 1v11即可。

    所以3个物品只需1次,9个物品只需2次,27个物品只需3次…… 3 n 3^n 3n个物品就只需n次。至于不是3的幂,则需要往上进一,用公式写就是: x = ⌈ log ⁡ 3 n ⌉ x=\lceil \log_3n \rceil x=log3n

    对于B类问题,则要复杂很多。


从13出发

    对于B类问题,我们举一个实际的例子,13个物品里有1个次品,答案是3次。我给出了具体的决策树:

在这里插入图片描述

    具体地,首先我们拿出8个,天平左右各4个,剩下5个(记作 4 v 4 ∼ 5 4v4\sim5 4v45)。如果天平是水平的,说明次品在剩下的5个里,不平则在这8个里,但由于不清楚次品和正品的轻重关系,因此无法确定在左边4个还是右边4个。

  1. 如果次品在剩下的5个里,我们拿出3个,和已确定是正品的8个里中的3个,放在天枰的左右侧(记作 3 v 3 ‾ ∼ 2 3v\overline{3}\sim2 3v32 3 ‾ \overline{3} 3表示3个正品)。如果天平是水平的,说明次品在剩下的2个里,不平则是在那3个里。
    1. 剩下的2个有次品的话,只要拿1个和1个正品称( 1 v 1 ‾ ∼ 1 1v\overline{1}\sim1 1v11),水平就是剩下的是次品,不平就是这个是次品
    2. 这3个有次品的话,我们发现我们其实已经知道了次品和正品的轻重关系,因为 3 v 3 3v3 3v3时。如果天平往左倒,说明次品更重;如果往右倒,说明次品更轻。知道轻重关系的话,这个问题就退化成A类问题了,3个物品就是 1 v 1 ∼ 1 1v1\sim1 1v11
  2. 如果次品在那8个里,第一次的天平有可能是往左倒,也有可能是往右倒,但是这两种情况其实是一样的,是对称的,那么不失一般性,我们只考虑往左倒的情况。我们拿出左边4个中的3个,和右边4个中的2个,放在天平左边,然后拿出5个正品(第一次称剩下的5个刚好)放在天平右边,进行称量(记作 ( 3 + 2 ) v 5 ‾ ∼ ( 2 + 1 ) (3+2)v\overline{5}\sim(2+1) (3+2)v5(2+1)),注意到这次称量只要不平,就可以得到轻重关系。如果水平,说明次品在剩下的2+1个;如果不平,说明次品在那3+2个中
    1. 剩下的2+1个有次品的话,我们取出左边1个和右边1个放在天平左边,再拿2个正品放在天平右侧,进行称量(记作 ( 1 + 1 ) v 2 ‾ ∼ ( 1 + 0
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
假硬币问题是一个经典的分治问题。假设你有 $n$ 枚硬币,其中有一枚是假的,比真的硬币轻。你可以使用天平来比较两堆硬币的重量。问你最少需要称多少次才能确定哪枚硬币是假的。 分治法是一种将问题分解成更小子问题的算法。在假硬币问题中,我们可以将硬币分成三组,然后比较其中两组,如果它们的重量相等,那么假硬币在第三组中;否则,假硬币在较轻的那组中。然后我们可以使用同样的方法继续在第三组中查找假硬币,递归执行下去,直到只剩下一枚硬币。 在每次比较中,我们总是能将硬币分成三组,因此每次比较的次数是固定的,即 $1$ 次。每次递归我们将问题规模缩小了 $3$ 倍,因此总的比较次数是 $T(n) = T(n/3) + 1$,解得 $T(n) = O(\log_3 n)$。 下面是一个使用分治法解决假硬币问题的 Python 代码: ```python def find_fake_coin(coins): n = len(coins) if n == 1: return coins[0] elif n % 3 == 0: # 将硬币分成三组,分别称重 one_third = n // 3 left = coins[:one_third] middle = coins[one_third:2*one_third] right = coins[2*one_third:] # 比较左右两组的重量 if sum(left) == sum(right): # 假硬币在中间一组 return find_fake_coin(middle) elif sum(left) < sum(right): # 假硬币在左边一组 return find_fake_coin(left) else: # 假硬币在右边一组 return find_fake_coin(right) else: # 如果硬币不能被分成三组,我们可以在两端添加一些真硬币 # 使得硬币数变成 3 的倍数 k = n - (n // 3) * 3 coins += [1] * (3 - k) return find_fake_coin(coins) ``` 其中,`coins` 是一个列表,表示所有硬币的重量。函数返回假硬币的重量。如果硬币不能被分成三组,我们可以在两端添加一些真硬币,使得硬币数变成 3 的倍数。这里我们添加了重量为 $1$ 的真硬币,因为它不会影响结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值