http://codeforces.com/problemset/problem/148/D
题意:有一个袋子,其中有w个白老鼠,b个黑老鼠,公主和魔王打赌,两个人轮流摸出一只老鼠不放回(因为魔王动作很粗鲁,所以每次魔王抓出一只老鼠,剩下的老鼠中就有随机一只跳出,不计入后面的比赛),先抓出白色的为赢家,公主先手,问公主是赢家的概率。
f[i][j]表示公主摸袋子前一时刻时袋子中有i只白老鼠j只黑老鼠的概率,因为如果公主或魔王摸出一只白老鼠时游戏立即结束,所以能转移到f[i][j]的状态只有f[i+1][j+2]或f[i][j+3],从而推出状态转移方程。
那么算出任意的f[i][j]之后再将所有情况下公主抓到白老鼠的概率相加即为公主为赢家的概率,需要注意的是,i或j可以为0但是不能同时为0。
大概是写过的最给人信心的题了,我真tm是个天才。
代码
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=1010; 9 const double eps=1e-8; 10 const int modn=998244353; 11 int w,b; 12 double f[maxn][maxn]={}; 13 int main(){ 14 scanf("%d%d",&w,&b); 15 f[w][b]=1.0; 16 for(int i=w;i>=0;i--){ 17 for(int j=b;j>=0;j--){ 18 if(i==w&&b==j)continue; 19 if(i==0&&0==j)continue; 20 f[i][j]+=f[i+1][j+2]*(i+1)*(j+2)*(j+1)/(1.0*(i+j+1)*(i+j+2)*(i+j+3)); 21 f[i][j]+=f[i][j+3]*(j+3)*(j+2)*(j+1)/(1.0*(i+j+1)*(i+j+2)*(i+j+3)); 22 } 23 } 24 double ans=0; 25 for(int i=0;i<=w;i++){ 26 for(int j=0;j<=b;j++){ 27 if(i==0&&j==0)continue; 28 ans+=f[i][j]*i/(1.0*(i+j)); 29 } 30 } 31 printf("%.9f ",ans); 32 return 0; 33 }