题目链接:http://codeforces.com/problemset/problem/148/D
题意:A,B两个人,a个白球,b个黑球,A和B轮流操作,A首先操作,其操作为从a和b中随机选出一个球,不放回,B的操作同A,在B操作完后(即每一轮结束后)从白球堆和黑球堆中随机去掉一个球。 AB中先获得白球的获胜,如果当前局面上已经没有球了则B获胜,问A获胜的概率。
思路:概率dp,递推式改了很多次,最后确定为
dp[i][j][0]表示当前局面为i个黑球,j个白球,轮到A取时,之前A,B取出的都是黑球的概率。
dp[i][j][1]表示当前局面为i个黑球,j个白球,轮到B取时,之前A,B取出的都是黑球的概率。
状态转移就是
dp[i-1][j][1]+=dp[i][j][0]*(i/(i+j));
dp[i-2][j][0]+=dp[i][j][0]*(i/(i+j))*0.5;
dp[i-1][j-1][0]+=dp[i][j][0]*(i/(i+j))*0.5;
最后再加一下,求出总概率即可。
注意i+j等于0的情况啊,会发生除零的,本来以为i+j等于0的情况其概率都为0,后来发现我错了,在这个地方wa了两炮。
code:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=1100;
double dp[maxn][maxn][2];
void debug(int a,int b)
{
for(int i=b;i>=0;i--){
for(int j=a;j>=a;j--){
printf("dp[%d][%d][0]=%.9f dp[%d][%d][1]=%.9f\n",i,j,dp[i][j][0],i,j,dp[i][j][1]);
}
}
}
int main()
{
int a,b;
double res;
scanf("%d%d",&a,&b);
memset(dp,0,sizeof(dp));
res=0.0;
dp[b][a][0]=1.0;
for(int i=b;i>=0;i--){
for(int j=a;j>=0;j--){
if(i-1>=0) dp[i-1][j][1]+=dp[i][j][0]*((double)i/(i+j));
if(i-2>=0) dp[i-2][j][0]+=dp[i][j][1]*((double)i/(i+j))*((double)(i-1)/(i+j-1));
if(i-1>=0&&j-1>=0) dp[i-1][j-1][0]+=dp[i][j][1]*((double)i/(i+j))*((double)j/(i+j-1));
}
}
for(int i=0;i<=b;i++){
for(int j=0;j<=a;j++){
if(!dp[i][j][0]) continue;
if(i+j==0) continue;
res+=dp[i][j][0]*((double)j/(i+j));
}
}
printf("%.9f\n",res);
return 0;
}