540D

原题链接:http://codeforces.com/problemset/problem/540/D

题意:给你石头、剪刀、布的数量,它们之间的石头能干掉剪刀,剪刀能干掉布,布能干掉石头,问最后石头、剪刀、布各自只有一种存活的概率。

思路: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 #include <bits/stdc++.h>  
 2 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
", res);
43     return 0;
44 }
原文地址:https://www.cnblogs.com/MasterSpark/p/7455281.html