• 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;
    }
    
    
  • 相关阅读:
    【LeetCode-树】二叉搜索树中第K小的元素
    【机器学习-评估方法】模型评估方法
    【LeetCode-树】二叉搜索树的最小绝对差
    【LeetCode-树】检查平衡性
    【LeetCode-树】验证二叉搜索树
    【LeetCode-回溯/动态规划】不同路径
    Vue——风格指南
    潜在危险
    渲染HTML的方式
    Vue——状态管理
  • 原文地址:https://www.cnblogs.com/A-sc/p/12945009.html
Copyright © 2020-2023  润新知