原题链接: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 }