现在的位置: 首页 > 综合 > 正文

147 金币概率问题(威盛笔试题)

2018年05月02日 ⁄ 综合 ⁄ 共 2294字 ⁄ 字号 评论关闭

题目:10 个房间里放着随机数量的金币。每个房间只能进入一次,并只能在一个房间中拿
金币。一个人采取如下策略:前四个房间只看不拿。随后的房间只要看到比前四个房间都多
的金币数,就拿。否则就拿最后一个房间的金币。
编程计算这种策略拿到最多金币的概率。

解法如下:

1.理论分析

2.编程求解

一.理论分析

设随机放入的10个房间的金币从小到大排序后是g1, g2, g3, ... , g10.

1.假设我们采用开四个房间的策略。
令看过的四个房间中的金币最大值是m。那么要获得最后胜利的话,
m只能等于g4, g5, g6, g7, g8, g9中的一个。

当 m=g4 时,这时看过的四个房间金币分布有4!种可能,即g1, g2, g3, g4进行全排列。
后面6个房间排布可能性有6!种。而总排布的可能性是10!。
在进入之后的6个房间时,如果房间里的金币数是g5-g9中的任意一个,都比m大,都要拿,则任务失败。
也就是说,这种情况下,获胜的可能性是1/6(6个房间里必须第一次选中g10金币房间)。
或者换种说法:第5个房间必须是g10才能赢。

推出当 m=g4 时,
p(win|m=g4) = (1/6) * (4! * 6!) / 10! = 1/1260
p(win|m=g4) = 1*5! *(4!) / 10! = 1/1260(第5个房间固定g10,后面5中全排列) 

当m=g5时,看过的四个房间里有三个房间含有的金币数量是g1, g2, g3, g4 中的三个。
剩下的一个必然在后面六个房间的一个里。
也就是说,进入后6个房间时进到金币数少于g5的房间不会失败也不会获胜。
那么获胜概率取决于剩下的5个房间,即1/5。

当 m=g5 时,
p(win|m=g5) = (1/5) * c(4 3) * (4! * 6!) / 10! = 2/525
p(win|m=g5) = 6 *1*4! * (c(4 3)* 4! ) / 10! = 2/525
同理可得

p(win|m=g6) = (1/4) * c(5 3) * (4! * 6!) / 10! = 1/84
p(win|m=g7) = (1/3) * c(6 3) * (4! * 6!) / 10! = 2/63
p(win|m=g8) = (1/2) * c(7 3) * (4! * 6!) / 10! = 1/12
p(win|m=g9) = c(8 3) * (4! * 6!) / 10! = 4/15

或者直观表示:
p(win|m=g6) = 6*5*1*3! * (c(5 3)* 4! ) / 10! 
p(win|m=g7) = 6*5*4*1*2! * (c(6 3)* 4! ) / 10! 
p(win|m=g8) = 6*5*4*3*1*1! * (c(7 3)* 4! ) / 10! 
p(win|m=g9) = 6*5*4*3*2*1* (c(8 3)* 4! ) / 10! 

把以上6种情况的概率全部加起来(因为是独立事件)
即是四房间策略的获胜概率:2509/6300,约等于0.3982539683。



进一步验证,考虑只看三个房间的策略:
p(win|m=g3) = (1/7) * (3! * 7!) / 10! = 1/840
p(win|m=g4) = (1/6) * c(3 2) * (3! * 7!) / 10! = 1/240
p(win|m=g5) = (1/5) * c(4 2) * (3! * 7!) / 10! = 1/100
p(win|m=g6) = (1/4) * c(5 2) * (3! * 7!) / 10! = 1/48
p(win|m=g7) = (1/3) * c(6 2) * (3! * 7!) / 10! = 1/24
p(win|m=g8) = (1/2) * c(7 2) * (3! * 7!) / 10! = 7/80
p(win|m=g9) = c(8 2) * (3! * 7!) / 10! = 7/30
相加的结果是3349/8400,约等于0.3986904762。
只看3个房间的获胜概率确实比4个房间要略高一点点。

二.编程求解

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

//rand()的用法  rand()不需要参数,它会返回一个从0到最大随机数的任意整数,
//最大随机数的大小通常是固定的一个大整数。
int genrand(int a, int b)
{
	return rand()%(b-a+1)+a;
}

void gennum(int *a,int size)//随机产生10个数 
{
	for (int i=0;i<size;i++)
	{
		a[i]=genrand(1,10000);
	}
}

int getnum(int *a, int size)//按规则取出的数
{
	int i,max=0;
	for (int i=0;i<4;i++)
	{
		if (a[i]>max) 
			max=a[i];
	}
	for (i=4;i<size-1;i++)
	{
		if (a[i]>max)
		 return a[i]; 
	}
	return a[size-1];
}

int getmax(int *a, int size)
{
	int max=0;
	for (int i=0;i<size;i++)
	{
		if (a[i]>max) max=a[i];
	}
	return max;
}

int success(int *a, int size)
{
	gennum(a,size);//随机产生10个数 
	if(getnum(a,size)==getmax(a,size))//按规则取出的数是否最大的数 
		return 1;
	return 0; 
}

int main()
{
	int a[10];
	int total=10000000;
	int count,k;
	k=0;
	while(k++<5)
	{
		count=0;
		for (int i=0;i<total;i++)
		{	
			if(success(a,10)) 
				count++;
		}
		cout<<"第"<<k<<"次,结果:"<<(double)count/(double)total<<endl;	
	}
	return 0;
} 

抱歉!评论已关闭.