称球问题|信息量|拓展|C++代码实现|12大小一样的球,找出其中质量不一样的球解析和代码实现

直接求解法
条件:天平、12个一样的球,其中一个不一样,用天平找出那个不一样的球并确定轻还是重,最少的次数是:3

将12个球分为三组
A:1 2 3 4
B:5 6 7 8
C:9 10 11 12

第一次称A组和B组

(1)若平衡:说明C组不正常:

第二次称C组中任意三个如:9 10 11和任意前三个

**(1.1)**若平衡则是C组中剩余那个12不平衡。
第三次称12与其他任意一个称,12在上则12轻,否则12重。

**(1.2)**若不平衡:说明 C组中被称的三个不正常;12正常,且根据倾斜可以判断不一样的球是重还是轻!
第三次称将C组中被称的三个再取两个称一下
若平衡则剩下那个不一样
若不平衡,则根据倾斜判断是哪个球!

(2)若不平衡:说明A和B组中的前八个不平衡
此时有斜率可以帮助判断后面

第二次称C组中任意三个如:9 10 11搭配B组中的8和5 6 7 4称、
组成E D称
(2.1) 若ED平衡说明A组中1 2 3不一样
第三次称1 2 3任意两个称
若一样,则剩下那个不一样(根据第一次称A组上下判断轻重,若A下则不一样的球重否则轻)
若不一样,(根据第一次称A组上下判断轻重,若A下则此组中下的球重否则轻)

(2.2) 若ED不平衡说明D中的5 6 7 4和E组中的8不一样
若AB倾斜与DE倾斜一样说明4和8不一样
第三次称 4和8中任意一个与另一个称,若平衡,则另外一个不一样根据选取得到球和剩下的那个球最初位于AB组和倾斜可判断轻重

若AB倾斜与DE倾斜不一样说明4和8不影响结果
影响的是5 6 7
在使这三个中两个称:
因为此种情况是B组不一样,根据B倾斜来判断轻重。
如上可以判断出是哪个。

—————————————————————————————

用信息论解释:
参考: http://blog.sciencenet.cn/blog-677221-669159.html.
里面大佬讲的超级详细!

信息量的公式:

H=∑-pi log pi

如果计算中的对数log是以2为底的,那么计算出来的信息就以比特(bit)为单位。
根据香农的信息概念,信息能消除不确定性,而我们在解决数学题的时候,也是要消除不确定性,得到确定的答案。并不仅仅是老鼠问题和称球问题如此,我认为大多数问题都多少是一个‘消除不确定性’ 的过程。因此,我们为何不借用香农的工具,研究研究我们的问题有多少不确定性呢?也就是说,需要多少信息量才能解决这个问题?另外,根据题目所限制的手段,最多能够得到多少信息量?有无可能完全解决这个问题?等等。

对于此问题:
12个球都不知轻重,那么每一个球都有轻/重之分,12个球就有24种可能
且未称之前这些球的轻重的概率都一样1/24
运用公式:要确定出这些球的信息量为:log24

对于秤来说:
每称一次其结果为:相等 左重右轻 左轻右重
其以上概率为1/3
秤能提供的信息量为log3

我们要做的是用称去求解球的信息
可以理解为秤的信息量要能得到球的信息量
即:称的次数*秤的信息量>=球的信息量
x * log3>=log24
所以x的最小值为3
—————————————————————————————
拓展
称球问题是说,用天平称k次,在n个球中找出唯一的一个重量不标准的次品球来,n最大是多少?如何找?有关这个次品球的说法,通常有3种变形:

1.已知次品球是更轻(或更重);

2.不知次品球的轻重,找出它并确定轻重;

3.不知次品球的轻重。

利用信息熵的概念,可计算出这3种情形下n的最大值,并且帮助思考构成算法的过程:

1.已知次品球是更轻(或更重),这时n的最大值 = 3**k;

2.不知次品球的轻重,找出它并确定轻重,这时n的最大值 = (3**k-3)/2;

3、不知次品球的轻重,这时n的最大值 = (3**k-1)/2。

还有老鼠药的问题等

用信息熵求解更快!
—————————————————————————————
代码实现

#include<iostream>
#include<time.h>
#include <stdlib.h>
using namespace std;
typedef int Status;

//每次随机产生12个球的重量,11个相同,1个不同
//每次打乱顺序,并显示出来
//调用dif_Ball函数能找到12个球中不一样的那个球的位置,并表示轻重及大小!


Status find_difBall(int *arr,int num_)
{
    
    
	int A, B, C;
	int t;
	//分组
	t = num_ / 3;
	A = B = C = 0;
	for (int i = 0; i < t; i++)//将12个球的质量分为3组,且能得知每组的质量!
	{
    
    
		A += arr[i];//前三个0-3
		B += arr[i + t];//4-7
		C += arr[i + 2 * t];//8-11
	}
	//首先先将AB分组秤 会有三种情况,A>B A<B A=B
	if (A > B)//第一次秤A>B
	{
    
    
		//如果A>B,也就是不平衡,
		//将AB换元素
		A = (A - arr[0] - arr[1] - arr[2] + arr[4] + arr[5] + arr[6]);//新的一组为4 5 6 7
		B = (B-arr[4]-arr[5]-arr[6]+arr[8]+arr[9]+arr[10]);//新的一组为8 9 10 11

		if (A > B)//A>B第二次秤
		{
    
    
			//如果新的AB不平衡,则前三个球正常,剩下的4和8不正常
			if (arr[3] > arr[0])//取4号球与正常球相比 第三次秤
				cout << "4号球是重球,重量为:" << arr[3] << "g" << endl;//4号球与前两次秤都是重,说明不一样的球是4号球且质量大一些
			else
				cout << "8号球是轻球,重量为:" << arr[7] << "g" << endl;//此时4号球只能是和正常球一样重,说明8号球是轻球
		}
		else if (A < B)//A<B说明5 6 7球有一个是轻球
			{
    
    
				if (arr[4] < arr[5])
					cout << "5号球是轻球,重量为:" << arr[4] << "g" << endl;
				else if(arr[4]>arr[5])
					cout<<"6号球是轻球,重量为:" << arr[5] << "g" << endl;
				else
					cout << "7号球是轻球,重量为:" << arr[6] << "g" << endl;
			}
		else//A=B,说明1 2 3 号球中有质量不一样的球
		{
    
    
			if(arr[0]<arr[1])
				cout << "2号球是重球,重量为:" << arr[1] << "g" << endl;
			else if(arr[0]>arr[1])
				cout << "1号球是重球,重量为:" << arr[0] << "g" << endl;
			else
				cout << "3号球是重球,重量为:" << arr[2] << "g" << endl;
		}
	}
	else if (A < B)//第一次秤A<B
	{
    
    
		//如果A<B,也就是不平衡,
		//将AB换元素
		A = (A - arr[0] - arr[1] - arr[2] + arr[4] + arr[5] + arr[6]);//新的一组为4 5 6 7
		B = (B - arr[4] - arr[5] - arr[6] + arr[8] + arr[9] + arr[10]);//新的一组为8 9 10 11
		if (A < B)//第二次秤A<B方向一致,球在4或8中
		{
    
    
			if (arr[3] < arr[0])
				cout << "4号球是轻球,重量为:" << arr[3] << "g" << endl;
			else
				cout << "8号球是重球,重量为:" << arr[7] << "g" << endl;
		}
		else if (A > B)//5 6 7不正常,且偏重
		{
    
    
			if(arr[4] > arr[6])
				cout << "5号球是重球,重量为:" << arr[4] << "g" << endl;
			else  if(arr[4]<arr[6])
				cout << "7号球是重球,重量为:" << arr[6] << "g" << endl;
			else
				cout << "6号球是重球,重量为:" << arr[5] << "g" << endl;
		}
		else//123中有轻球
		{
    
    
			if (arr[0]<arr[1])
				cout << "1号球是轻球,重量为:" << arr[0] << "g" << endl;
			else if (arr[0]>arr[1])
				cout << "2号球是轻球,重量为:" << arr[1] << "g" << endl;
			else
				cout << "3号球是轻球,重量为:" << arr[2] << "g" << endl;
		}
	}
	else//(A=B)
	{
    
    
		int E, F;
		E = arr[8] + arr[9] + arr[10];
		F = arr[0]+arr[1]+arr[2];
		if (E > F)//重球
		{
    
    
			if (arr[9] > arr[8])
				cout << "10号球是重球,重量为:" << arr[9] << "g" << endl;
			else if(arr[9]<arr[8])
				cout << "9号球是重球,重量为:" << arr[8] << "g" << endl;
			else
				cout << "11号球是重球,重量为:" << arr[10] << "g" << endl;
		}
		else if (E < F)
		{
    
    
			if (arr[9] > arr[8])
				cout << "9号球是轻球,重量为:" << arr[8] << "g" << endl;
			else if (arr[9]<arr[8])
				cout << "10号球是轻球,重量为:" << arr[9] << "g" << endl;
			else
				cout << "11号球是轻球,重量为:" << arr[10] << "g" << endl;
		}
		else
		{
    
    
			if(arr[11]>arr[0])
				cout << "12号球是重球,重量为:" << arr[11] << "g" << endl;
			else
				cout << "12号球是轻球,重量为:" << arr[11] <<"g"<< endl;
		}
	}
	return 0;
}

Status main()
{
    
    
	//int i;
	srand(time(NULL));//rand函数加上此可以每次产生不一样的值
	int Ball[12];
	int num = rand() % 99+ 1;//产生一个值在1-100之间的值,令数组所有元素都为该值。
	for (int i = 0; i < 12; i++)
	{
    
    
		Ball[i] = num;
	}
	int a = rand() % 11 + 0;//产生一个0-11之间的值,并随机赋予数组0-11之中的元素
	Ball[a] = rand() % 99 + 1;
	if (Ball[a] == Ball[a + 1] && Ball[a] == Ball[a - 1])//如果其中一个值与另外的值相等,则重新来过
	{
    
    
		Ball[a] = rand() % 99 + 1;
	}
	cout << "显示所有球重量:" << endl;
	for (int i = 0; i < 12; i++)//产生之后在屏幕上显示出所有的元素
	{
    
    
		cout << Ball[i] << "g ";
	}
	cout << endl;
	cout << endl;
	cout << "找出那个不一样的球并显示其重量!" << endl;
	int dif_Ball = find_difBall(Ball, 12);//调用该函数找出不一样的值

	//cout << dif_Ball << "是不一样的那个球" << endl;

	return 0;

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_46096297/article/details/109701099
今日推荐