题意:有r个石头,s个剪刀,p个布,求在足够长一段时间后,石头、剪刀、布分别存活下来的概率。
思路:概率dp,定义dp[i][j][k],表示有i个石头,j个剪刀,k个布情况下的概率。
状态转移方程:dp[i-1][j][k]=dp[i-1][j][k]+dp[i][j][k]*i*k/(i*j+i*k+j*k); 表示布包石头的情况,石头-1。
ansr表示石头最终存活下来的概率。对所有dp[i][j][0]求和即可,即布已为0,石头一定存活。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=105;
double dp[N][N][N];
int main(){
int r,s,p;
double ansr=0,anss=0,ansp=0;
scanf("%d%d%d",&r,&s,&p);
memset(dp,0,sizeof(dp));
dp[r][s][p]=1;
for(int i=r;i>=1;i--){
for(int j=s;j>=1;j--){
for(int k=p;k>=1;k--){
int temp=i*j+i*k+j*k;
dp[i-1][j][k]+=dp[i][j][k]*i*k/temp;
dp[i][j-1][k]+=dp[i][j][k]*j*i/temp;
dp[i][j][k-1]+=dp[i][j][k]*k*j/temp;
}
}
}
for(int i=r;i>=0;i--){
for(int j=s;j>=0;j--){
ansr+=dp[i][j][0];
}
}
printf("%.12f ",ansr);
for(int i=s;i>=0;i--){
for(int j=p;j>=0;j--){
anss+=dp[0][i][j];
}
}
printf("%.12f ",anss);
for(int i=r;i>=0;i--){
for(int j=p;j>=0;j--){
ansp+=dp[i][0][j];
}
}
printf("%.12f\n",ansp);
return 0;
}