地址:http://codeforces.com/problemset/problem/148/D
思路:这是第三道概率DP,不同于前两道,这一道题做时有些感觉,越做越像数位DP,尤其是本题用搜索来写。本题是回溯时求答案,因为尽管相同情况的不同种求法用记忆化搜索减少了运算,但是对于答案来说,每种情况都要计入在内,所以只用记忆化会多省一些数据。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
double p[1010][1010]; //double型数组不能用memset全置为-1
bool vis[1010][1010]; //所以这里开了个bool型辅助,这里坑了我半天
double dfs(int w,int b) //非常像数位DP搜索写法
{
if(w<=0) return 0;
if(b<=0) return 1;
if(vis[w][b]) return p[w][b];
vis[w][b]=1;
double ans=w*1.0/(w+b);
if(w&&b>1)
{
double s;
s=1.0*b*(b-1)/(w+b)/(w+b-1);
ans+=s*((b-2)*1.0/(w+b-2)*dfs(w,b-3)+w*1.0/(w+b-2)*dfs(w-1,b-2));
}
p[w][b]=ans;
return ans;
}
int main()
{
int w,b;
scanf("%d%d",&w,&b);
printf("%.9f\n",dfs(w,b));
return 0;
}