称球问题解析(2)-N球方法

作者: Phill King

邮箱: phillking1982@163.com

原创文章,转载请注明出处。

有N个外表一模一样的小球,除了有一个小球略轻或略重,其他的小球质量都是一样的。求用没砝码的天秤最少称多少次,才能找出的异常球,并且知道它是更轻还是更重?

本文介绍一种三进制(Ternary)编码的方法来解决任意数目的称球问题。

通常我们对二进制编码更为熟悉,二进制编码由0,1构成。而三进制编码由0,1,2构成。

我们先引入三进制正序数和逆序数的概念:

正序数:

  从左到右第一次变化是0->1, 1->2, 2->0。 如010,201等。

逆序数:

  从左到右第一次变化和正序数相反: 1->0, 2->1, 0->2。 如100,211等。

性质:

1. 正序数的 3 进制补码为逆序数: 001  <=>   221
2. 正序数和逆序数在 ( 0 - 3^{n} ) 范围内对称,且数目一样多
3. 本文 我们用正序数代表小球更重,逆序数代表小球更轻。

对于每一轮的称量,我们都将N个小球分成三组。同时给每个小球两个三进制编码。以12个小球为例:

第i论的称量规则:

第i次称,根据编码第i位的数值决定放置位置。0 放在左边,2放在右边。1不称。

假设六号小球是异常球:

 那么根据我们的称量规则,可以根据每一轮的结果获取异常球的三进制编码。

假设6号球更重,简单分析一下过程:

1. 第一轮:6号球编码是120.第一位是1,所以放在旁边不称。第一轮的结果是平衡,记录1.

2. 第二轮:6号球第二位编码是2,放在天平的右边。6号球更重,第二轮结果是左边轻,记录2

 3.第三轮:6号球第三位编码是0,放在左边。第三轮结果是左边重,记录0.

结果的编码是120,和6号球的正序数编码是一样的。如果6号球偏轻,结果是102和6号球的逆序数编码是一样的。

以上分析了12球的情况,那如果球的数目不能被3整除的时候。应该怎么做呢?

我们再引入三元组的概念:

三元组:

编码的每一位进行 0->1, 1->2, 2->0 转换 , 三个为一组 例如 : 012->120->201
同一个三元组的元素根据规则永远都会分配到不同的位置
我们利用三元组确保每次称球的平衡
例子 : 012->120->201

 结合三元组的分配规则如下:

1. 当总数能够被 3 整除时,按照三元组分配
2. 如果不能够被 3 整除时,为了保持第一次称球时的平衡 :
1. 如果剩余一个球,分配 1 开头的编码。第一次不称。
2. 如果剩余两个球,分别分配 0 2 开头的编码。第一次分别放在左右。

                后续出现称球不平衡时,用第一次称后已知的正常球补足。

下面以8个球为例:

 编码方案:

 具体过程:

 ###代表已知的正常球。第一轮至少可以获知两个正常球。通常我们只需要一个来保证天平两侧的平衡即可。这里仍然以6号球为例分析,读者可以自行假设一个异常球,根据其编码进行分析。

接下去我们分析一下使用该方法测量N个球的最少次数:

假设一共测n轮:

  1. n和三进制的长度一样
  2. 不能使用的编码(备注:在称球问题的一些变体中可以使用这些编码):
    1. 全1编码。如果一直不称量,无法知道其轻重
    2. 全0和全2编码。如果000和222代表同一个球,无法确定放在哪一边。

n位三进制的总数位3^{n},每个球需要两个编码。 所以我们一共可以测: \frac{3^{n} - 3}{2} 个球。

综上,我们可以确定对于jN个球称量的通用方法:

1. 通过公式 \frac{3^{n}-3}{2} >= N 确定称球次数 n ,将 n 作为三进制的位数

2. 构造 n 位三进制的正逆序三元组编码
3. 给每一球分配一对编码(正序和逆序)
4. 当总数不能被 3 整除时,需要处理多余的球
1. 如果多 1 个,分配 1 开头的编码。后续左右数目不平时用已知正常球补足
2. 如果多 2 个,分配 0 2 开头的编码。后续左右数目不平时用已知正常球补足
5. 每一轮根据编码对应位的值放置小球,并记录结果

结果编码所对应的小球即为异常球,并可根据编码的正逆序获知轻重。

根据公式可以推论称量次数和小球数目的关系:

1.2次最多3个小球

2.3次最多12个小球

3.4次最多39个小球

4.5次最多120个小球

扩展问题:

针对一些称球问题的变体,仍然可以用三进制编码方法来解决。

  1. 假如不需要知道异常球的轻重,可测  \frac{3^{n} - 1}{2}
    1. 增加一个球,编码为全1.  有且仅有一种情况无法知道轻重。
  2. 假如另外有一个已知正常球(不计算在可测球数内),可测 \frac{3^{n} - 1}{2}  
    1. 选一球编码为全0和全2, 始终放在左侧。额外正常球不编码,第一次放在右侧平衡。
  3. 结合1&2\frac{3^{n} + 1}{2}

总结:

本文介绍了用三进制(Ternary)编码方法解决称球问题的方案。下一篇文章会提供一个称球问题公式的证明:n次称量,最多可以测 \frac{3^{n} - 3}{2}个球。

称球问题解析(3) - 公式证明_Phill.King的博客-CSDN博客

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 要使用MATLAB求解三个球的交点,可以按照以下步骤进行: 1. 首先,定义三个球的参数:心坐标(xi, yi, zi) 和半径ri,其中i表示第i个球。这些参数可以通过输入或给定的数据来获取。 2. 使用MATLAB的符号计算功能,将的方程表示为变量x,y和z的方程。例如,假设我们有三个球心坐标分别为(x1, y1, z1),(x2, y2, z2)和(x3, y3, z3),半径分别为r1,r2和r3,则第一个球的方程为(x-x1)^2 + (y-y1)^2 + (z-z1)^2 = r1^2。 3. 将三个球的方程联立,求解交点的解析解。使用MATLAB的方程求解函数,可以将三个球的方程转化为一个方程组,并求解出变量x,y和z的值。函数的输入是方程组和未知数向量[x, y, z],输出是解向量[x0, y0, z0]。 4. 对于无解或有无穷解的情况,可以通过添加一些额外的约束条件来解决,例如限制解在特定的范围内。可以对解向量进行筛选,根据实际需求选择正确的解。 5. 最后,使用MATLAB的绘图功能绘制三个球和交点的三维图形。将三个球心和半径作为参数传递给绘制函数,并在图形中显示交点的位置。 总结: 使用MATLAB可以通过符号计算和方程求解功能求解三个球的交点。这个过程包括定义的参数,转化方程为方程组,并求解出交点的解析解。最后,使用MATLAB绘图功能将三个球和交点可视化。 ### 回答2: 要使用MATLAB求解三个球的交点,可以利用MATLAB的求解器来计算。首先,定义三个球的半径和中心坐标,然后使用方程组来表示这三个球的交点问题。 假设A的半径为r1,B的半径为r2,C的半径为r3。A的中心坐标为(x1,y1,z1),B的中心坐标为(x2,y2,z2),C的中心坐标为(x3,y3,z3)。 得到的方程组如下: (x-x1)^2 + (y-y1)^2 + (z-z1)^2 = r1^2 (x-x2)^2 + (y-y2)^2 + (z-z2)^2 = r2^2 (x-x3)^2 + (y-y3)^2 + (z-z3)^2 = r3^2 使用MATLAB中的solve函数可以求解这个方程组。首先,将方程转换为多项式的形式,然后使用solve函数求解方程组。MATLAB会返回一个包含交点坐标的向量。 以下是一个求解三个球交点的MATLAB代码示例: % 定义的半径和中心坐标 r1 = 1; x1 = 0; y1 = 0; z1 = 0; r2 = 1; x2 = 1; y2 = 0; z2 = 0; r3 = 1; x3 = 0.5; y3 = 1; z3 = 0; % 定义方程组 eq1 = '(x-x1)^2 + (y-y1)^2 + (z-z1)^2 - r1^2'; eq2 = '(x-x2)^2 + (y-y2)^2 + (z-z2)^2 - r2^2'; eq3 = '(x-x3)^2 + (y-y3)^2 + (z-z3)^2 - r3^2'; % 解方程组 sol = solve(eq1, eq2, eq3, 'x', 'y', 'z'); % 获取交点坐标 x = double(sol.x); y = double(sol.y); z = double(sol.z); % 输出交点坐标 disp('交点坐标:'); for i = 1:length(x) fprintf('点%d:(%f, %f, %f)\n', i, x(i), y(i), z(i)); end 使用这个代码示例,可以通过定义三个球的半径和中心坐标,然后求解方程组,获得三个球的交点坐标。请根据实际情况修改代码中的的半径和中心坐标。 ### 回答3: 要计算三个球的交点,可以使用Matlab中的数值计算功能。以下是一个使用Matlab计算三个球的交点的示例代码: ```matlab % 定义三个球的参数 % 1:(x-a1)^2 + (y-b1)^2 + (z-c1)^2 = r1^2 a1 = 1; b1 = 2; c1 = 3; r1 = 2; % 2:(x-a2)^2 + (y-b2)^2 + (z-c2)^2 = r2^2 a2 = -3; b2 = 0; c2 = 1; r2 = 3; % 3:(x-a3)^2 + (y-b3)^2 + (z-c3)^2 = r3^2 a3 = 2; b3 = 1; c3 = -2; r3 = 2; % 建立符号变量 syms x y z; % 构造三个球的方程 eq1 = (x-a1)^2 + (y-b1)^2 + (z-c1)^2 - r1^2; eq2 = (x-a2)^2 + (y-b2)^2 + (z-c2)^2 - r2^2; eq3 = (x-a3)^2 + (y-b3)^2 + (z-c3)^2 - r3^2; % 联立三个球的方程求解交点 [x_sol, y_sol, z_sol] = solve(eq1, eq2, eq3, x, y, z); % 显示结果 disp("交点的坐标:"); for i = 1:length(x_sol) disp(['点', num2str(i), ':']); disp(['x:', char(x_sol(i))]); disp(['y:', char(y_sol(i))]); disp(['z:', char(z_sol(i))]); end ``` 以上代码首先定义了三个球的参数,并使用符号变量定义了三个球的方程。然后通过`solve`函数联立三个球的方程求解交点的坐标。最后,使用`disp`函数显示交点的坐标。 请根据实际情况修改的参数,并运行代码得到三个球的交点坐标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值