参考链接:https://www.cnblogs.com/Howe-Young/p/5514371.html
题意:给你w个白色小鼠和b个黑色小鼠,把他们放到袋子里,princess先取,dragon后取,princess取的时候从剩下的当当中任意取一个,dragon取得时候也是从剩下的时候任取一个,但是取完之后会随机跳出来一个。取到每个小鼠的概率是一样的,跳出的也是一样的。先取到白色的小鼠赢,问最后princess能赢的概率。
思路:概率dp,如果把princess能赢的分成两种情况,那么这个题就是递推了,我是用记忆化搜索写的。首先,用dp[i][j]表示袋子当中还有i个白色的,j个黑色的princess能取赢的概率。那么有两种情况:
1.这一步能取赢,那么就是直接取到白色的,概率为i/(i+j);
2.这一步取不赢,那么当前一定是取到黑色的,因为最后要让princess赢,所以,接着dragon也取不赢,现在还有一个问题是,跳出的小鼠的颜色,那么又分为两种情况:
1). 跳出的为白色的。概率就是j/(i+j)*(j-1)/(i+j-1)*(i)/(i+j-2)*dp[i-1][j-2]
2). 跳出的位黑色的。概率就是j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2)*dp[i][j-3]
推到这里基本上就出来了,剩下的边界条件了。如果i==0,那么概率一定是0, 如果i>0&&j==0那么概率一定为1.
代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 #include<map> 7 #include<vector> 8 #include<math.h> 9 #define mem(a,x) memset(a,x,sizeof(a)) 10 using namespace std; 11 typedef long long LL; 12 const int maxn=1005; 13 const int mod=26; 14 const int INF=0x3f3f3f3f; 15 const int Times = 10; 16 const int N = 5500; 17 double dp[maxn][maxn]; 18 double dfs(int w,int b) 19 { 20 //b<0证明上一次dfs的行为不可取 21 if(w<=0 || b<0) return 0; 22 if(w>0 && b==0) return dp[w][b]=1; 23 if(dp[w][b]!=-1) return dp[w][b]; 24 double temp1=(double)w/(w+b); //直接取到白球 25 double temp2=(double)b/(w+b); 26 dp[w][b]=temp1; 27 if(w+b>2) //为了防止分母为0 28 { 29 double ans1=dfs(w,b-3)*(b-1)/(w+b-1)*(b-2)/(w+b-2); 30 double ans2=dfs(w-1,b-2)*(b-1)/(w+b-1)*(w)/(w+b-2); 31 temp2*=(ans1+ans2); 32 dp[w][b]+=temp2; 33 } 34 return dp[w][b]; 35 } 36 int main() 37 { 38 int w,b; 39 cin>>w>>b; 40 for(int i=0;i<=w;++i) 41 { 42 for(int j=0;j<=b;++j) 43 dp[i][j]=-1; 44 } 45 printf("%.9lf ",dfs(w,b)); 46 }