天平秤重问题(三进制)

[问题描述]:
 有一只天平和N只砝码,如何设计这N只砝码,才能使这天平能够连续秤出的重量最大?假设砝码的最小单位为1克,秤物时物品放在天平的左边,砝码可以放在右边也可以放在左边,不管放在哪一边只要天平能够平衡就行,物品的重量应是右边砝码总重量减去左边砝码的重量。
输入一个物品的重量,输出其秤重方案。
 [分析与算法选择]:
 这个问题是从一个经典的数学问题变化而来,这个数学问题的大意是:一个物体重40磅,掉在地上后摔成四片,这四片恰好能够作为砝码连续秤出40磅以内的物品的重量,这四片的重量如何?
 (1)如何设计砝码?
 我们先不去看单位,直接用数字来描述。因为要能连续秤出一范围内的值,所以首先要有1,从数学上可以知道,N只砝码本身最大能秤的总重就是这N只砝码的重量和,下面就看如何保证连续的数都能秤出了。设这N只砝码的重量分别为W1、W2……Wn,且有W1<=W2<=……<=Wn, W1=1,下面看W2如何设计。
 如果W2=1,1、2都能秤出;如果W2=2,1、2、3都能秤出;如果W2=3,1可以秤出(W1)、2可以秤出(W2-W1)、3可以秤出(W2)、4也可以秤出(W1+W2);如果W2=4,则2不能秤出;所以W2最大为3(=3*W1)。
 同理可推出W3最大为9(=3*W2);
 ……
 Wn最大为3n-1(=3*Wn-1)。
 设计方案为这N只砝码重分别为:1、3、9、27、……、3^n-1。
 (2)如何根据物品重量得到秤重方案?
    物品(+砝码)         砝码

因为物品固定放在一连(如左边),只要考虑砝码放的情况。任一个砝码都可能有三种状态:一是跟被秤物品放在一起(如左边),二是不放,三是放在物品另一边(如右边)。最后物品的重量等于所有砝码乘上相应系数的和。这个系数可能是:-1、0、1。

先来看3只砝码时各种重量的称法,如下表所示,其中-1表示砝码放在物品一边、0表示砝码不放进天平、1表示砝码放在物品另一边,如果每一位加1后便只会是0、1、2这3个数字中的一个,所以可以方便地跟三进制数对应起来:

物品重量

3只砝码

每一位加1

9

3

1

三进制数

十进制数

1

0

0

1

112

14(=1+13)

2

0

1

-1

120

15(=2+13)

3

0

1

0

121

16(=3+13)

4

0

1

1

122

17(=4+13)

5

1

-1

-1

200

18(=5+13)

6

1

-1

0

201

19(=6+13)

7

1

-1

1

202

20(=7+13)

8

1

0

-1

210

21(=8+13)

9

1

0

0

211

22(=9+13)

10

1

0

1

212

23(=10+13)

11

1

1

-1

220

24(=11+13)

12

1

1

0

221

25(=12+13)

13

1

1

1

222

26(=13+13)

由上表我们可以总结出这样的计算方法:对于给定的物品重量,先确定它最多用到多大的砝码,假定是3n-1,那么先将这个物品的重量加上1、3、……3n-1,得到一个数,再对这个数进行除3取余运算,当余数为0时表示相应的砝码跟物品放在一起,余数为1时表示相应的砝码不放,为2时表示放在物品的另一边。


 

假币问题也被称为分量秤问题,通常用于算法设计,特别是二分搜索和贪心策略。对于n个硬币,目标是最小化秤次数来确定哪一个是较轻的那个。一个常见的解决方案是使用二进制分割法。 以下是利用分治策略的一个简单算法步骤,以n=101为例: 1. 第一次称:将硬币分为两组,每组50个和51个。如果平衡,则假币在未称的那一组(51个),如果不平衡,则假币在较轻的那一边。 2. 第二次称:如果第一次不平衡,继续对包含假币的一组进行细分,再次分成两个部分,每个部分25个和26个硬币。再次称,假币在较轻的一边。 3. 以此类推,每次都将剩余硬币数除以2并加上1,直到剩下最后一组,这一步只需一次称就能确定哪个是假币。 代码示例(Python语言): ```python def find_fake_coin(coin_weights): n = len(coin_weights) # 使用二分法,直至只剩下一个元素 while n > 1: mid = n // 2 left = coin_weights[:mid] right = coin_weights[mid:] # 判断两边是否平衡 if sum(left) == sum(right): # 平衡,假币在剩下的部分 n = mid else: return 'Left' if sum(left) < sum(right) else 'Right' # 不平衡,假币在轻的一边 # 如果只剩下一个硬币,它就是假币 return 'Single' # 示例 coin_weights = [True] * 101 + [False] # 真币标记为True,假币为False print(find_fake_coin(coin_weights)) ``` 这个过程理论上最多需要log2(n)次称,对于n=101,也就是4次就能确定假币。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值