• Flipping Coins (概率DP)


    题目链接
    比赛地址

    题目:

    将N个相同的硬币排成一排,所有的硬币正面朝上向下放到桌子上,尾巴向上,然后执行K次操作每次取一枚硬币,抛出得到正面或反面。最后正面朝上的硬币可以拿走。问可以赢得的最大预期金额是多少?

    思路:

    期望公式 (Ex = A * p(A)) A表示是一个事件,P(A)是A发生的概率。这道题也是这样想的。最后正面朝上的个数num可能是1~n个。所以(res = num * P(num))。问题变为求P(num),即最后num个硬币正面朝上的概率。

    用dp求P(num)。我们用dp[i][j]表示i次操作后有j个正面朝上的概率,这样总共k次操作,所以P(num)=dp[k][num]。 如何转移呢?我们已知dp[0][0] = 1;

    当正面朝上个数j小于n时,我们要优先对正面朝下的硬币先操作,每次操作后抛出硬币有可能正有可能背面向上。所以由dp[i][j]可以更新dp[i+1][j]和dp[i+1][j+1]。
          j < n 时,dp[i + 1][j + 1] += dp[i][j] * 0.5;
                    dp[i + 1][j] += dp[i][j] * 0.5;
          
    当正面朝上个数j等于n时,我们只能选正面向上的硬币操作,有正有负,所以可能会减少向上个数。所以do[i][n]可以更新dp[i+1][j]和dp[i+1][j-1];
          j == n 时 dp[i+1][j] += dp[i][j] * 0.5;
                    dp[i+1][j-1] += dp[i][j] * 0.5;
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<vector>
    #include<string>
    #include<fstream>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 1e3 + 105;
    const int mod = 998244353;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    //
    
    int n, k;
    double dp[N][N];
    
    int main()
    {
        scanf("%d%d",&n,&k);
        memset(dp, 0,sizeof(dp));
        dp[0][0] = 1;
        for(int i = 0; i < k; ++ i){
            for(int j = 0; j < n; ++ j){
                dp[i + 1][j] += dp[i][j] * 0.5;
                dp[i + 1][j + 1] += dp[i][j] * 0.5;
            }
            dp[i + 1][n] += dp[i][n] * 0.5;
            dp[i + 1][n - 1] += dp[i][n] * 0.5;
        }
        double res = 0;
        for(int i = 1; i <= n; ++ i){
            res += i * dp[k][i];
        }
        printf("%.6lf
    ",res);
        return 0;
    }
    
    
  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/A-sc/p/12945009.html
Copyright © 2020-2023  润新知