题目链接:https://codeforces.com/problemset/problem/540/D
题目大意:一个岛上有x个石头,y个剪刀,z个布,每两个东西打架的概率相等,石头打败剪刀,剪刀打败布,布打败石头,求最后只剩石头、剪刀、布的概率
题目思路:dp[i][j][k]分别表示剩下i个石头 j个剪刀 k个布。转移方程很类似,以少了个石头举例,也就是dp[i-1][j][k],少了个石头就说明石头跟布打架了,石头跟布打架的方案数是i*k,也就是石头数量乘以布的数量,所有的方案数是i*j+i*k+j*k也就是石头跟剪刀,石头跟布,剪刀跟布的方案数之和。那么dp[i-1][j][k]+=dp[i][j][k]*(1.0*i*k)/(1.0*i*j+i*k+j*k),其他所有情况与此同理
以下是代码:
#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(ll i=a;i>=b;i--)
#define ll long long
const ll MAXN = 5e5+5;
const ll MOD = 1e9+7;
int r,s,p;
double dp[105][105][105];
int main()
{
while(~scanf("%d%d%d",&r,&s,&p)){
memset(dp,0,sizeof(dp));
dp[r][s][p]=1;
per(i,r,0){
per(j,s,0){
per(k,p,0){
int temp=i*j+i*k+j*k;
if(i&&k)dp[i-1][j][k]+=dp[i][j][k]*(1.0*i*k)/(1.0*temp);
if(j&&i)dp[i][j-1][k]+=dp[i][j][k]*(1.0*i*j)/(1.0*temp);
if(k&&j)dp[i][j][k-1]+=dp[i][j][k]*(1.0*j*k)/(1.0*temp);
}
}
}
double ans1=0,ans2=0,ans3=0;
rep(i,1,r)ans1+=dp[i][0][0];
rep(i,1,s)ans2+=dp[0][i][0];
rep(i,1,p)ans3+=dp[0][0][i];
printf("%.9lf %.9lf %.9lf\n",ans1,ans2,ans3);
}
return 0;
}