题目描述
一共有N个红球,M个蓝球。三个人参与(A,B,C),A,B先取到红球者胜利,两者都没有取到红球,则B胜利。C只取球,不参与胜负。按照A,B,C的次序依次取球。问A胜出的概率。
解题思路
在每次博弈中,A胜出的概率取决于以下三种情况:
- A直接取到红球。
- A,B依次都取到蓝球,C取到红球,再进入下次博弈,即N-1个红球,M-2个蓝球。
- A,B,C依次都取到蓝球,,再进入下次博弈,即N个红球,M-3个蓝球。
显然可以用递归或是动态规划来解题。
测试用例
1 1
样例输出
0.50000
提示
输入样例2
3 4
输出样例2
0.62857
解题代码
- 动态规划
#include <iostream>
#include <vector>
#include <cstdio>
#include <iomanip>
using namespace std;
float probaOfAWin(int n, int m)
{
vector<vector<float> > dp(n+1, vector<float>(m+1));
// 初始化dp
for(int i = 0; i < n+1; i++)
{
// 蓝球为0,则概率为1
dp[i][0] = 1.0;
}
// 红球为0,则概率为0
for(int i = 0; i < m+1; i++)
dp[0][i] = 0.0;
for(int i = 1; i < n+1; i++)
{
for(int j = 1; j < m+1; j++)
{
// A 直接取到 red
float A_Red = i * 1.0 / (i + j);
dp[i][j] += A_Red;
// A blue and B blue
float B_Blue = (1-A_Red) * ((j-1) * 1.0 / (i + j-1));
if(j >= 2)
{
// A blue and B blue and C red
float C_Red = B_Blue * (i * 1.0 / (i + j-2));
dp[i][j] += C_Red * dp[i-1][j-2];
}
if(j > 2)
{
// A blue and B blue and C blue
float C_Blue = B_Blue * ((j-2) * 1.0 / (i + j-2));
dp[i][j] += C_Blue * dp[i][j-3];
}
}
}
return dp[n][m];
/* 递归:可能细节处理不正确
if(m == 0 && n != 0)
return 1;
if(n == 0)
return 0;
int sum = 0;
// A red
float A_Red = n * 1.0 / (n + m);
// B blue
float B_Blue = (1-A_Red) * ((m-1) * 1.0 / (n + m-1));
// C red
float C_Red = B_Blue * (n * 1.0 / (n + m-2));
// C blue
float C_Blue = B_Blue * ((m-2) * 1.0 / (n + m-2));
sum += A_Red + C_Red * probaCore(n-1, m-2) + C_Blue * probaCore(n, m-3);
return sum;
*/
}
int main()
{
int n, m;
cin >> n >> m;
float res = probaOfAWin(n, m);
// 格式化输出 1
printf("%.5f\n", res);
// 格式化输出 2: 自动补0
cout.setf(ios::fixed);
cout << setprecision(5) << res <<endl; //精度为5,输出5位数
cout.unsetf(ios::fixed);
// 格式化输出 3: 自动补0
cout << fixed;
cout << setprecision(5) << res <<endl;
cout.unsetf(ios::fixed);
return 0;
}