请教一道概率题
一个箱子里有r个红球和b个蓝球,球的个数之和是奇数。A和B一起玩一个游戏,首先A从箱子里随机取出一个球(取到每个球的概率是一样的),然后B从箱子里取出一个蓝球,依次进行下去。
当轮到B取时,箱子里没有可取的蓝球,则B获胜;如果最后一个从箱子里取出的球是蓝球,则A获胜,否则B获胜。
问:给出红球的个数r和蓝球的个数b,求A获胜的概率?
感觉应该dp,谁能详细讲一下?
[解决办法]
用递归实现的,效率不高,呵呵。大家提点改进意见
double SelectBall(int redBall, int blueBall){ if (!(redBall >= 0 && blueBall >= 0 && (redBall + blueBall) % 2 == 1)) { printf("Input Error!"); return 0; } int nRed = redBall; int nBlue = blueBall; double res = 0; if (blueBall == 0)//蓝球为0个。如果红球大于1,则A必赢(A取后B无球可取),如果红球等于1,则A必输 { if (redBall == 1) return 0; else return 1; } if (redBall == 0)//红球取完了,最后一定是A取到蓝球,获胜 { return 1; } //进入这里的 redball blueball都是大于等于1的 if (blueBall == 1)//只剩一个蓝球,且红球数不为0. 取到蓝球赢,否则进入下一轮 { return blueBall * 1.0 / (redBall + blueBall) + redBall * 1.0 / (redBall + blueBall) * SelectBall( redBall - 1, blueBall - 1); } //进入这里的redball >= 1, blueball >= 2; return redBall * 1.0 / (redBall + blueBall) * SelectBall(redBall-1, blueBall-1) + blueBall * 1.0 / (redBall + blueBall) * SelectBall(redBall, blueBall-2);}int main(){ int redBall = 5; int blueBall = 10; while(1) { printf("Input Red ball count and Blue ball count:\n"); scanf("%d %d", &redBall, &blueBall); if (redBall < 0 || blueBall < 0) { break; } double AWin = SelectBall(redBall, blueBall); printf("(%d, %d) =%f\n", redBall, blueBall, AWin); }}
[解决办法]
上代码吧。。SRM408 DIV2 1000
#include <iostream>using namespace std;double result=0;double pa[1001][4000]={0};class MarblesInABag{public: double getProbability(int red,int blue) { if(red>blue) return 0; else if(red>1000) return 0; else if(red==0) return 1; else if(blue==0) return 0; else if(pa[red][blue]) return pa[red][blue]; else{ double a=(double)(red)/(double)(red+blue); double b=(double)(blue)/(double)(red+blue); pa[red][blue]=a*getProbability(red-1,blue-1)+b*getProbability(red,blue-2); return pa[red][blue]; } }};
[解决办法]
尝试了一下,如果球数过大,动态建表比递归方式效率高得多。
#define MAXRED 4011
#define MAXBLUE 8010
double f[MAXRED][MAXBLUE]={0};
double TabSelectBall(int redBall, int blueBall)//返回A获胜的概率
{
int i,j;
for(j=1;j<=blueBall;j++)//所有红球为0的情况,概率为1
f[0][j]=1.0;
for(i=1;i<=redBall;i++)
for(j=0;j<i;j++)
f[i][j]=0.0;
for(int i=1;i<=redBall;i++)
for(int j=i+1;j<=blueBall;j+=2)//蓝球数必须要大于红球数才不为0,
f[i][j]=(f[i-1][j-1]*i+f[i][j-2]*j)/(i+j);
return f[redBall][blueBall];
};