题目链接
题意
在一座岛上,有r个人只会出石头,有s个人只会出剪刀,有p个人只会出布,很不幸的是上帝现在只希望岛上最终只有1种人存活。问r,s,p存活的概率分别为多少
题解
概率DP
- 我们定义dp[i][j][k]三维分别表示三种人剩余的个数,数组记录的值是当前这个状态出现的概率。
定义pi,pj,pk,和sum,假设当前存活i,j,k,sum = i * j+i * k+j * k;(总相遇的可能情况)
pi = (i*k) / sum : i 和 k相遇,i被干掉的概率
pj = (i*j) / sum : i 和 j 相遇,j被干掉的概率
pk = (j*k) / sum: j 和 k相遇 ,k被干掉的概率由全概率公式 dp[i][j][k] = pi * dp[i+1][j][k] + pj * dp[i][j+1][k] + pk * dp[i][j][k+1]
- 最后我们统计每种导致各种类型的人必胜的局势的概率,输出结果即可。
代码
/**
dp[i-1][j][k] += dp[i][j][k] * (i*k) / (i*k+i*j+j*k);
dp[i][j-1][k] += dp[i][j][k] * (i*j) / (i*k+i*j+j*k);
dp[i][j][k-1] += dp[i][j][k] * (j*k) / (i*k+i*j+j*k);
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 110;
double dp[maxn][maxn][maxn]; ///表示剩余[r][s][p]个人时的概率。
int main()
{
int r,s,p;
while(~scanf("%d%d%d",&r,&s,&p))
{
memset(dp,0,sizeof(dp));
dp[r][s][p] = 1.0;
for(int i=r;i>=1;i--)
for(int j=s;j>=1;j--)
for(int k=p;k>=1;k--)
{
int sum = i*j+i*k+k*j;
dp[i-1][j][k] += dp[i][j][k] * (i*k*1.0/sum); /// +=
dp[i][j-1][k] += dp[i][j][k] * (i*j*1.0/sum);
dp[i][j][k-1] += dp[i][j][k] * (j*k*1.0/sum);
}
double ans1 = 0,ans2 = 0,ans3 = 0;
for(int i=1;i<=100;i++) ///一定存活者则从1开始
for(int j=0;j<=100;j++) ///必胜局势 i 为 j 的天敌。
{
ans1 += dp[i][j][0];
ans2 += dp[0][i][j];
ans3 += dp[j][0][i];
}
printf("%.10f %.10f %.10f\n",ans1,ans2,ans3);
}
return 0;
}