得到红球的最大概率

今天面试被问到一个问题:有红白两色球各50个,按照一定分配方法放入两个框子中,另一个人随机从某个框子抓取一个球,问怎样分配可以令第一次抓取到红球的概率最大?

我一开始想当然地回答如此如此这般这般,抓到红球的概率是0.5,……可能由于面试有些紧张,这样的答案有一个非常明显的bug,当时没有意识到,等到面试一结束突然想起来——第一次抓到红球和白球的概率和是1,如果抓到红球最大概率是0.5,翻译过来就是抓到白球的最小概率是0.5,而红球白球没有本质的区别,两者的概率问题应该能够互换。除非不论怎么分配,抓到某种球的概率永远都是0.5,否则我之前的答案就很有矛盾,而我们知道这样的情形是不可能的。

总之,我的回答是大错特错的!!

所以正确答案应该是什么呢?我在平静下来之后继续思考——

首先,框子一共有两个,那么选择拿球的框子时,每种概率都是0.5

假设从第一个框子中拿到红球的概率是p1,从第二个框子中拿到红球的概率是p2,那么最终抓取到红球的概率是p=0.5*(p1+p2)

此时,如果一个框子中(假设是第一个框子)只用红球,而另一个框子中有红球和白球,那么p1=1,0<p2<1,于是p=0.5 + 0.5*p2。这样的结果绝对大于0.5。

再次证明我之前的回答没动脑子。

剩下的就好想了。为了使p2尽可能地大,那么第二个框子中的红球要尽可能的多,很容易得出第一个框子放一个红球,第二个框子放49个红球和50个白球这样的结论,此时第一次抓取到红球的概率最大,约为0.75

稍稍扩展一下,如果小球的数量不是50个呢?那么球的数量越多,最后越接近于0.75,因为这样的p2越接近1。


为了进行验证,我写了如下代码(其中小球数量的初始值可自定):

/************************************/
/** File's name:                   **/
/**     cal.c                      **/
/** Usage:                         **/
/**     cal.exe NUMBER_OF_RED_BALL **/
/** Written by Si*4                **/
/************************************/
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      

double** MallocBall(int num)
{
	int sz = sizeof(double)*num;
	int psz = sizeof(double*)*num;
	double **ball = NULL;
	ball = (double**)malloc(psz);
	int i,j;
	for(i = 0; i < num; i++)
	{
		ball[i] = (double*)malloc(sz);
		for(j = 0; j < num; j++)
		{
			ball[i][j]=0.0f;
		}
	}
	return ball;
}

int FreeBall(double **ball, int num)
{
	int i;
	for(i = 0; i < num; i++)
		if(ball[i] != NULL) free(ball[i]);
	free(ball);
	ball = NULL;
	return num;
}

//	the number of ball in one basket
double Cal(int this, int that, int num)
{
	double p1, p2;
	p1 = (this + that == 0)?0:(double)this/(this+that);
	p2 = (this + that == num*2)?0:(double)(num - this)/(num*2 - this - that);
	p1 = (p1 + p2)/2;
	return p1;
}

void Output(double **ball, int num)
{
	FILE *pf = fopen("output.txt", "wt");// 打开文件
	if(pf == NULL) 
	{
		printf("Open file output.txt failed.\n");
		return;
	}
	printf("r/w");						// 打印第一行标签
	fprintf(pf, "r/w");
	int r, w;
	for(w = 0; w <= num; w++)
	{
		printf("%5d", w);
		fprintf(pf, "%5d", w);
	}
	printf("\n");
	fprintf(pf, "\n");
	for(r = 0; r <= num; r++)			// 打印结果矩阵(精确到小数点后2位)
	{
		printf("%3d");
		fprintf(pf, "%3d");
		for(w = 0; w <= num; w++)
		{
			printf(" %.2lf", ball[r][w]);
			fprintf(pf, " %.2lf", ball[r][w]);
		}
		printf("\n");
		fprintf(pf, "\n");
	}
	putchar('\n');
	if(pf != NULL) fclose(pf);			// 关闭文件
}

int main(int argc, char* argv[])
{
	int n;
	sscanf(argv[1], "%d", &n);
	printf("There are %d red balls and %d white balls.\n", n, n);
	double **red = MallocBall(n+1);		// 二维数组
	int r, w;							// r和w分别表示在第一个框子中红、白球的个数
	for(r = 0; r <= n; r++)				// 验证所有可能性
	{
		for(w = 0; w <= n; w++)
		{
			double tmp = Cal(r, w, n);	// 计算概率
			red[r][w] = tmp;
		}
	}
	Output(red, n);						// 输出结果(包括屏幕和文件)
	FreeBall(red, n+1);					// 释放内存
	return 0;
}
     
     
    
    
   
   

当两种小球个数是10,20,30时结果如下:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值