题意:
原来袋子里有w只白鼠和b只黑鼠
龙和王妃轮流从袋子里抓老鼠。谁先抓到白色老鼠谁就赢。
王妃每次抓一只老鼠,龙每次抓完一只老鼠之后袋里会有一只老鼠跑出来。
每次抓老鼠和跑出来的老鼠都是随机的。
原来袋子里有w只白鼠和b只黑鼠
龙和王妃轮流从袋子里抓老鼠。谁先抓到白色老鼠谁就赢。
王妃每次抓一只老鼠,龙每次抓完一只老鼠之后袋里会有一只老鼠跑出来。
每次抓老鼠和跑出来的老鼠都是随机的。
如果两个人都没有抓到白色老鼠则龙赢。王妃先抓。
问王妃赢的概率。
dp(x,y,wch) 表示还有x只黑鼠,y只白鼠,到wch==0?王妃:龙 抓,王妃赢的概率
轮到王妃抓dp(x,y,0)的转移:
(1)抓只白的 dp(x,y,0)+=dp(x,y-1,1); 这时dp(x,y-1,1)== 有x只黑鼠y只白鼠,抓黑鼠的概率:y/(x+y);
(2)抓只黑的 dp(x,y,0)+=dp(x-1,y,1)*x/(x+y);
轮到龙抓dp(x,y,1)的转移,因为考虑的是王妃的胜率,所以龙抓白鼠的情况忽略:
(1)抓只黑的跑了黑的 dp(x,y,1)+=dp(x-2,y,0)*(x/(x+y))*((x-1)/(x+y-1));
(2)抓只黑的跑了白的 dp(x,y,1)+=dp(x-1,y-1,0)*(x/(x+y))*(y/(x+y-1));
特别的dp(x,0,0),dp(x,0,1) 王妃都必败 dp(0,y,0)王妃必胜,dp(0,y,1)王妃必败 。还有些边界问题的细节需要注意下。
我用的是记忆化搜索解决
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn=1008;
const double eps=1E-8;
double dp[maxn][maxn][2];
//还有x只黑鼠,y只白鼠,到wch==0?王妃:龙 抓,王妃赢的概率
int w,b;
double DP(int x,int y,int wch)
{
// printf("%d %d %d\n",x,y,wch);
if(!y) return 0;//没有白色王妃输
if(!x)
{//没有黑色
if(!wch) return 1;//王妃抓白
else return 0;
}
double &res=dp[x][y][wch];
if(res>-0.5) return res;//已搜索过
res=0;
double bk=(double)x,wt=(double)y;
if(!wch)
{//王妃抓
if(y>0) res=wt/(wt+bk);//抓白
if(x>0) res+=DP(x-1,y,1)*(bk/(wt+bk));//抓黑
}
else
{//让龙抓
//抓黑跑黑
if(x>1) res+=DP(x-2,y,0)*(bk*(bk-1)/((wt+bk)*(wt+bk-1)));
//抓黑跑白
if(x>0&&y>0)res+=DP(x-1,y-1,0)*(bk*wt/((wt+bk)*(wt+bk-1)));
}
return res;
}
int main()
{
while(~scanf("%d%d",&w,&b))
{
memset(dp,-1,sizeof(dp));
printf("%.10lf\n",DP(b,w,0));
}
return 0;
}