题意:袋子里有w只白鼠,b只黑鼠。公主和龙谁先抓到第一只白鼠谁就获胜,都抓不到白鼠,算龙获胜。 两人轮流抓,每次只能抓一只,公主先抓。龙在抓老鼠的时候,老鼠会因为害怕而每次从袋子中爬出来一只。问公主获胜的机会有多大?
题解:我们可以用dp[i][j]表示在有i只白鼠,j只黑鼠的时候公主获胜的概率。 于是我们能够得到以下几点:
1.当 b=0时, 0<i<=w,dp[i][0]=1;当w=0时,0<=i<=b,dp[0][i]=0 ;
2.公主直接抓到一只白鼠时,王妃赢了,概率为 i/(i+j) ;
3.公主抓到一只黑鼠,龙抓到一只白鼠,公主输了,概率为 j/(i+j)*(i)/(i+j-1) ;由于dp[i][j]表示公主获胜的概率,这种情况就不用考虑进入状态转移,我们接着往下看;
4.公主抓到一只黑鼠,龙抓到一只黑鼠,从袋子中跑了一只黑鼠,概率为 j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2) ,转态就转移到了dp[i][j-3],当然出现这种情况的限制在于 j>=3 ;
5.公主抓到一只黑鼠,龙抓到一只黑鼠,从袋子中跑出来一只白鼠,概率为 j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2) , 转态就转移到了 dp[i-1][j-2],出现这种情况 必须 j>=2 ;
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1010
double dp[maxn][maxn];
int main()
{
int w,b;
int i,j;
while(scanf("%d%d",&w,&b)!=EOF)
{
memset(dp,0,sizeof(dp));
for(i=1;i<=w;++i)
dp[i][0]=1;
for(i=1;i<=w;++i)
{
for(j=1;j<=b;++j)
{
dp[i][j]+=(double)i/(i+j);
if(j>=3)//公主抓到黑鼠,龙也抓到黑鼠,从袋子中跑了一只黑鼠
dp[i][j]+=(double)j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2)*dp[i][j-3];
if(j>=2)//公主抓到黑鼠,龙也抓到黑鼠,从袋子中跑了一只白鼠
dp[i][j]+=(double)j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2)*dp[i-1][j-2];
}
}
printf("%.9lf\n",dp[w][b]);
}
return 0;
}