codeforces 540D 概率dp

传送门

大概可以这样理解, 一开始有r个石头, p个布, s个剪刀, 每一天有其中的两个相遇, 如果两个是相同的种类, 什么都不会发生, 否则的话有一个会挂掉, 问最后每一种生存的概率。

dp[i][j][k]表示到达i个石头, j个布, s个剪刀的概率, 那么初始状态dp[r][p][s] = 1。 状态转移方程为dp[i-1][j][k] = i*k/tot*dp[i][j][k], tot是当前所有相遇的情况, tot = i*j+i*k+j*k。

最后求每一种的生存的概率, 如果是石头生存, 那么显然只要布为0, 石头的个数>0, 而剪刀的个数无论有多少个都可以。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pb(x) push_back(x)
 4 #define ll long long
 5 #define mk(x, y) make_pair(x, y)
 6 #define lson l, m, rt<<1
 7 #define mem(a) memset(a, 0, sizeof(a))
 8 #define rson m+1, r, rt<<1|1
 9 #define mem1(a) memset(a, -1, sizeof(a))
10 #define mem2(a) memset(a, 0x3f, sizeof(a))
11 #define rep(i, a, n) for(int i = a; i<n; i++)
12 #define ull unsigned long long
13 typedef pair<int, int> pll;
14 const double PI = acos(-1.0);
15 const double eps = 1e-8;
16 const int mod = 1e9+7;
17 const int inf = 1061109567;
18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
19 double dp[101][101][101];
20 int main()
21 {
22     int a, b, c;
23     cin>>a>>b>>c;
24     mem(dp);
25     dp[a][b][c] = 1.0;
26     for(int i = a; i>=1; i--) {
27         for(int j = b; j>=1; j--) {
28             for(int k = c; k>=1; k--) {
29                 double tot = i*j+j*k+i*k;
30                 dp[i-1][j][k] += 1.0*(i*k)/tot*dp[i][j][k];
31                 dp[i][j-1][k] += 1.0*(j*i)/tot*dp[i][j][k];
32                 dp[i][j][k-1] += 1.0*(j*k)/tot*dp[i][j][k];
33             }
34         }
35     }
36     double ans1 = 0, ans2 = 0, ans3 = 0;
37     for(int i = 1; i<=a; i++)
38         for(int j = 0; j<=b; j++)
39             ans1 += dp[i][j][0];
40     for(int i = 1; i<=b; i++)
41         for(int j = 0; j<=c; j++)
42             ans2 += dp[0][i][j];
43     for(int i = 1; i<=c; i++)
44         for(int j = 0; j<=a; j++)
45             ans3 += dp[j][0][i];
46     printf("%.9f %.9f %.9f\n", ans1, ans2, ans3);
47 }

 

posted on 2015-12-03 14:41  yohaha  阅读(251)  评论(0)    收藏  举报

导航