题意:会出石头、剪刀、布的人分别有r,s,p个,他们相互碰到的概率相同,输的人死掉,问最终活下去的人是三种类型的概率。
因为是概率不是期望;所以从dp[r][s][p]推到dp[0][0][0];直接暴力三重循环
每一次跟新时的总情况一定是i*j+j*k+k*i;
然后如果剪刀减少一个的概率就是现有的(石头个数剪刀个数/总数)当前情况的概率;
即dp[i][j-1][k]+=dp[i][j][k]*(1.0*i*j/sum);//剪刀少一个;
其他同理;
最后若求剪刀存活概率,就是将dp【0】【j】【k】求和;
因为仅存剪刀和布,剪刀必赢,所以上面递推时没必要到两个0,只要1个0;
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
double dp[101][101][101];
int main(){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
memset(dp,0,sizeof(dp));
dp[a][b][c]=1;
for(int i=a;i>=1;i--){
for(int j=b;j>=1;j--){
for(int k=c;k>=1;k--){
int sum=i*j+j*k+k*i;
dp[i][j-1][k]+=dp[i][j][k]*(1.0*i*j/sum);//剪刀少一个;
dp[i-1][j][k]+=dp[i][j][k]*(1.0*i*k/sum);//石头少一个;
dp[i][j][k-1]+=dp[i][j][k]*(1.0*k*j/sum);//布少一个;
}
}
}
double ans=0;
for(int i=a;i>=0;i--){
for(int j=b;j>=0;j--)
ans+=dp[i][j][0];
}
printf("%.12f ",ans);
ans=0;
for(int k=c;k>=0;k--){
for(int j=b;j>=0;j--)
ans+=dp[0][j][k];
}
printf("%.12f ",ans);
ans=0;
for(int k=c;k>=0;k--){
for(int i=a;i>=0;i--)
ans+=dp[i][0][k];
}
printf("%.12f\n",ans);
return 0;
}