原题链接:
题意:给你石头、剪刀、布的数量,它们之间的石头能干掉剪刀,剪刀能干掉布,布能干掉石头,问最后石头、剪刀、布各自只有一种存活的概率。
思路:dp[i][j][k]为石头剪刀布分别剩下i,j,k个的概率。以布消灭石头为例,从dp[i][j][k]转移到dp[i-1][j][k]需要dp[i][j][k]乘上转移的概率总情况为tot=i*k+i*j+j*k,石头遇上布的情况为i*k,所以这里的概率为i*k/(i*k+i*j+j*k),则dp[i-1][j][k]=dp[i][j][k]*i*k/(i*k+i*j+j*k)。
当其中一种剩下0时结果便能知道,当其中一种剩下0时对另外两种的存活情况求和便得答案。
AC代码:
1 #include2 using namespace std; 3 double dp[105][105][105]; 4 int main() 5 { 6 int r, s, p; 7 scanf("%d %d %d", &r, &s, &p); 8 memset(dp, 0, sizeof(dp)); 9 dp[r][s][p]=1.0; 10 double tot;11 for(int i=r;i>=1;i--){12 for(int j=s;j>=1;j--){13 for(int k=p;k>=1;k--){14 if(dp[i][j][k]==0.0) continue;15 tot=(i*k+j*i+k*j)*1.0;16 dp[i-1][j][k]+=(i*k*1.0/tot)*dp[i][j][k];17 dp[i][j-1][k]+=(i*j*1.0/tot)*dp[i][j][k];18 dp[i][j][k-1]+=(j*k*1.0/tot)*dp[i][j][k];19 }20 }21 }22 double res=0.0;23 for(int i=1;i<=r;i++){24 for(int j=0;j<=s;j++){25 res+=dp[i][j][0];26 }27 }28 printf("%.12f ", res);29 res=0.0;30 for(int i=1;i<=s;i++){31 for(int j=0;j<=p;j++){32 res+=dp[0][i][j];33 }34 }35 printf("%.12f ", res);36 res=0.0;37 for(int i=1;i<=p;i++){38 for(int j=0;j<=r;j++){39 res+=dp[j][0][i];40 }41 }42 printf("%.12f\n", res);43 return 0;44 }