Problem Description
唐老师和狗哥在玩哗啦啦村的日常游戏——抓个球。
在袋子里有w个白球,b个黑球。
唐老师和狗哥轮流从袋子里抓球,谁先抓到白球谁就胜利。
但是,令唐老师和狗哥没想到的是,小彭玉居然来捣乱了!
每当唐老师和狗哥一回合抓球结束后(各抓取一个球),小彭玉会偷偷的抓取一个球走。
那么这时候,问题来了,当唐老师先手的时候,唐老师获胜的概率是多少呢?
假设所有抓球都是随机的。
Input
只有两个数字 w和b w<=1000 b<=1000
Output
输出唐老师赢的概率 保留9位小数
Sample Input
1 3
Sample Output
0.500000000
第一次就抓到了,或者没抓到,他也没抓到,第三个人偷白或者黑球,方程就是
f[x][y]=x/(x+y)+a*f[x-1][y-2]+b*f[x][y-3];
a,b为系数,具体的还要考虑到边界以及y的特判。
之前没有使用记忆化搜索,玩死我了- -,我加了一个数组来标记是否访问过,其实如果方便取哨兵值的时候,可以统一赋值一个哨兵值判断。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
int leap[1005][1005];
double dp[1005][1005];
double f(long long x,long long y)
{
double ans=x*1.0/(x+y);
if(y>=3)
{
if(!leap[x][y-3])
{
leap[x][y-3]=1;
dp[x][y-3]=f(x,y-3);
}
ans=ans+dp[x][y-3]*y*(y-1)*(y-2)/((x+y)*(x+y-1)*(x+y-2));
if(!leap[x-1][y-2])
{
leap[x-1][y-2]=1;
dp[x-1][y-2]=f(x-1,y-2);
}
ans=ans+dp[x-1][y-2]*x*y*(y-1)/((x+y)*(x+y-1)*(x+y-2));
return ans;
}
else if(y==2)
{
if(!leap[x-1][y-2])
{
leap[x-1][y-2]=1;
dp[x-1][y-2]=f(x-1,y-2);
}
ans=ans+dp[x-1][y-2]*x*y*(y-1)/((x+y)*(x+y-1)*(x+y-2));
return ans;
}
else if(y==1)
{
return ans;
}
}
int main()
{
long long i, j, m, n, t,w,b,x,y;
double ans;
cin>>w>>b;
memset(dp,0,sizeof(dp));
memset(leap,0,sizeof(leap));
for(i=1;i<=w;i++)
{
dp[i][0]=1;
leap[i][0]=1;
}
for(i=0;i<=b;i++)
{
dp[0][i]=0;
leap[0][i]=1;
}
leap[w][b]=1;
ans=f(w,b);
printf("%.9lf",ans);
cout<<endl;
return 0;
}