12球称重C语言算法,12小球称重问题

该博客详细介绍了如何利用无砝码天平,在三次称重内找出12个相同外观小球中的一个次品,并确定其是偏重还是偏轻。方法包括将小球分为三组,通过比较不同组合的重量变化,逐步缩小次品范围,最终确定次品及其重量属性。关键在于巧妙地安排称重组合,确保每次称重都能提供足够的信息来排除大部分正常球。
摘要由CSDN通过智能技术生成

题目:

已知有12个小球,一样的形状和外观,其中有一个是次品,现在给你一个无砝码的天平,称三次,

把这个次品找出来,并且求出这个次品相对真品是偏重还是偏轻?

解答:

首先把小球分成三堆,每堆四个。

A:(1,2,3,4)

B:(5,6,7,8)

C:(9,10,11,12)

情况 一:

1 第一称重

随便拿出两堆来称, 这里不妨假设拿出A和B

A(1,2,3,4)------------------------ B(5,6,7,8)

结果有两种可能性,第一种A和B相等,第二种A和B不相等。

对于第一种AB相等的情况。

那么C中肯定有一个次品了。接下来做第二次称重。

从AB中随便拿三个,从C中也随便拿三个

D(1,2,3)---------------  E(9,10,11)

第二次称重也有两种可能。

2.1 如果还是相等的话

那么剩下12就是次品。

第三次称重

随便拿一个球和最后剩下的12球相称就知道结果了。

2.2 如果第二次称重不相等的话。这里我们假设D

从E中任意拿两个出来做第三次称重。

F (10)------- G(11)

如果F==G 那么  9 是次品,而且次品是偏重的。

如果 F > G 那么   10 是次品,而且次品是偏重的。

如果 F < G 那么   11 是次品,而且次品是偏重的。

好了,到这里为止,对于一次称重出现相等的情况,我们已经给出了解答。

那么对于第一次称重就出现不相等的情况,我们做一下分析:

情况二:

1 第一称重 A B 不相等。我们不妨假设 A < B, 那么C中的9,10,11,12小球必然都是真品。注意这

个技巧是解决问题的关键。我们注意到这样一个事实如果只是交互真品,天平的状态是不会改变的。

好,我们做以下的交换

H (1,9,10,11) -----------------------------I(2,3,4,5)

因为我们知道9,10,11三个小球都是真品。现在做第二次称重。有两种情况:

2.1 天平保持原来的状态,也就是说 H < I, 那么我们可以知道2,3,4,6,7,8,9,10,11,12

都是真品,1,5小球中有一个是次品。好了,现在我们可以做第三次称重,从1,5中随便拿一个小球,

这里我们拿1小球,从2,3,4,6,7,8,9,10,11,12中随便拿一个,这里我们拿9小球。

做第三次称重,就可以知道结果了。

2.2 天平的状态发生了改变,这里还是有两种情况,第一种 H == I,第二种H > I

第一种 对于 H == I 来说,我们知道1,2,3,4,5 ,9,10,11,12 都是真品,

那么6,7,8,必定有一个是次品,因为,第一次称重的时候,我们知道 H < I ,那么也就是说次品是偏重的。

从6,7,8 任意拿出两个来称重,不妨拿出6,7做第三次称重,结果就出来了。

第二种 对于H > I 来说。我们可以知道2,3,4中必定有一个是次品。而且次品相对于真品来说是偏轻的。

因为原来 H < I ,现在是H > I ,那么必定是移动偏轻的次品才会导致这种情况。好,我们从2,3,4中

任意拿出两个,不妨拿出2,3 做第三次称重,就可以知道结果了。

解答完毕。

C语言中,我们可以使用递归或者循环的方式模拟这个过程。这里以递归为例来展示解决方案: ```c #include <stdio.h> int findLightBall(int balls[], int n, int weighings) { // 第一次称量 if (weighings == 0 || n <= 3) { for (int i = 0; i < n; i++) { if (balls[i] < balls[0]) return i + 1; } return 1; // 假设第一个是最轻的,因为没有其他选择 } // 分割成三份 int mid = n / 3; int left[3], right[3]; for (int i = 0; i < mid; i++) { left[i] = balls[i]; } for (int i = mid; i < 2 * mid; i++) { right[i - mid] = balls[i]; } // 第二次称量 int lighterSide; if (weigh(left, right, 1)) { // 左边重 lighterSide = 1; } else { // 右边重 lighterSide = 2; } // 第三次称量 int lightBallIndex = findLightBall(weighs[left[mid]], 3, weighings - 1); if (lighterSide == 1) return lightBallIndex + 1; else return lightBallIndex + mid + 1; } // 递归函数,传入已分割的数组和当前层数 int weighs(int arr[], int n, int depth) { // 实际测量,这里是假定arr[n-1]是最轻的 if (depth == 0) return 1; // 表示左边较轻 return n % 2 ? 0 : 1; // 假设偶数次称量时右边是轻 } int main() { int balls[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int n = sizeof(balls) / sizeof(balls[0]); printf("The index of the light ball is: %d\n", findLightBall(balls, n, 3)); return 0; } ``` 这个程序假设每次称重的结果都是随机的,实际上需要替换为实际的比较操作。注意,这是一个简化的例子,实际应用中需要处理更多的边界条件和错误检查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值