codeforces-148D Bag of mice【概率dp】

题意:

原来袋子里有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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值