【CodeForces148D】Bag of mice
题意
dragon和princess玩一个游戏。开始的时候袋子里有w个白老鼠和b个黑老鼠。两个人轮流从袋子里面往外摸老鼠。谁先拿到白老鼠谁先获胜。dragon每次抓出一只老鼠,剩下老鼠里面都会有一只跳出袋子。princess则不会。 princess先抓。问princess赢得概率是多少。
分析
简单的概率DP。我一看到两个人玩得这种游戏就习惯性的定义两个dp数组。
f[i][j][0]为当前袋子里有i只白老鼠,j只黑老鼠时,princess赢得概率
f[i][j][1]为当前袋子里有i只白老鼠,j只黑老鼠时,dragon赢得概率
状态的转移也很好想
f[i][j][0]=(1-f[i][j-1][1])*(j/(i+j))+i/(i+j).
f[i][j][1]=(1-f[i-1][j-1][0])*j/(i+j)*i/(i+j-1)+(1-f[i][j-2][0])j/(i+j)(j-1)/(i+j-1)+i/(i+j)
AC代码如下
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 const int maxn=1000+100; 8 int w,b; 9 double f[maxn][maxn][3]; 10 11 int main(){ 12 scanf("%d%d",&w,&b); 13 memset(f,0,sizeof(f)); 14 f[0][0][0]=0;f[0][0][1]=1.0; 15 for(int i=1;i<=w;i++) 16 f[i][0][0]=f[i][0][1]=1.0; 17 for(int i=1;i<=b;i++) 18 f[0][i][1]=1.0; 19 for(int i=0;i<=w;i++){ 20 for(int j=0;j<=b;j++){ 21 if(j==0||i==0) 22 continue; 23 if(j>=1){ 24 f[i][j][0]=(1-f[i][j-1][1])*j/(i+j)+(double)i/(i+j); 25 if(i>=1) 26 f[i][j][1]=(1-f[i-1][j-1][0])*(j*i)/((i+j)*(i+j-1))+(double)i/(i+j); 27 } 28 if(j>=2) 29 f[i][j][1]+=(1-f[i][j-2][0])*(j*(j-1))/((i+j)*(i+j-1)); 30 } 31 } 32 printf("%.9f",f[w][b][0]); 33 34 return 0; 35 }
然后我看网上大佬们一般一个数组就解决了。
令f[i][j]为当前有i个白老鼠,j个黑老鼠时,princess先手,赢得概率。
那么状态转移有几种可能性:
1.princess直接拿到了白老鼠,赢得了游戏,概率为i/(i+j)
2.princess拿到了黑老鼠,dragon拿到了黑老鼠,跳出来黑老鼠,概率为j/(i+j) * (j-1)/(i+j-1) * (j-2)/(i+j-2)
3.princess拿到了黑老鼠,dragon拿到了黑老鼠,跳出来一只白老鼠,概率为j/(i+j) * (j-1)/(i+j-1) * i/(i+j-2)
AC代码如下
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 const int maxn=1000+100; 8 double f[maxn][maxn]; 9 int w,b; 10 int main(){ 11 scanf("%d%d",&w,&b); 12 memset(f,0,sizeof(f)); 13 for(int i=1;i<=w;i++) 14 f[i][0]=1.0; 15 for(int i=1;i<=b;i++) 16 f[0][i]=0.0; 17 f[0][0]=0; 18 for(int i=1;i<=w;i++){ 19 for(int j=1;j<=b;j++){ 20 f[i][j]+=(double)i/(i+j); 21 if(j>=3){ 22 f[i][j]+=(double)j/(i+j)*(double)(j-1)/(i+j-1)*(double)(j-2)/(i+j-2)*f[i][j-3]; 23 } 24 if(j>=2){ 25 f[i][j]+=(double)j/(i+j)*(double)(j-1)/(i+j-1)*(double)i/(i+j-2)*f[i-1][j-2]; 26 } 27 } 28 } 29 printf("%.9f\n",f[w][b]); 30 return 0; 31 }