1.题目描述:点击打开链接
2.解题思路:本题利用概率dp解决。一开始想着如何推出每一个最终的概率公式,没有思路。最后发现其实可以通过概率dp解决。设状态d(i,j,k)为还有i个石头,j个剪刀,k个布时的概率,那么不难得到以下三个递推式:
d(i-1,j,k)+=d(i,j,k)*(i*k)/(i*j+i*k+j*k);
d(i,j-1,k)+=d(i,j,k)*(i*j)/(i*j+i*k+j*k);
d(i,j,k-1)+=d(i,j,k)*(j*k)/(i*j+i*k+j*k);
由于题目中i,j,k的最大范围只是100,可以直接用O(N*3)计算出所有的状态,最终的答案为ans=sum{d(i,0,0)|1≤i≤r}(后两种类似)。
3.代码:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<algorithm> #include<string> #include<sstream> #include<set> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<functional> using namespace std; typedef long long ll; #define me(s) memset((s),0,sizeof(s)) #define For(i,n) for(int i=1;i<=(n);i++) #define N 100+5 double dp[N][N][N]; int main() { //freopen("t.txt", "r", stdin); int r, s, p; while (cin >> r >> s >> p) { memset(dp, 0, sizeof(dp)); dp[r][s][p] = 1.0; for (int i = r; i >= 0;i--) for (int j = s; j >= 0;j--) for (int k = p; k >= 0;k--) if ((i&&j)||(j&&k)||(k&&i)) { double tot = i*j + i*k + j*k; if (k)dp[i][j][k - 1] += dp[i][j][k] * (double)j*k / tot; if (j)dp[i][j - 1][k] += dp[i][j][k] * (double)i*j / tot; if (i)dp[i-1][j][k] += dp[i][j][k] * (double) i*k / tot; } double s1, s2, s3; s1 = s2 = s3 = 0.0; For(i, r)s1 += dp[i][0][0]; For(i, s)s2 += dp[0][i][0]; For(i, p)s3 += dp[0][0][i]; printf("%.12lf %.12lf %.12lf\n", s1, s2, s3); } return 0; }