zoukankan      html  css  js  c++  java
  • 概率期望总结

    一.解题技巧:

    期望题倒着推,概率正着推
    经常和概率dp联系

    二.例题:

    **1.POJ 3744**

    详解:

    2.POJ - 3071 Football

    代码:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=(1<<7)+5;
    double p[N][N],win[N][10];//每个选手进入第i轮的概率
    int main()
    {
        int n;
        while(scanf("%d",&n),n!=-1)
        {
            int m=1<<n;
            double maxn=0;
            int num=1;
            for(int i=1;i<=m;i++)
            {
                for(int j=1;j<=m;j++)
                    scanf("%lf",&p[i][j]);
            }
            memset(win,0,sizeof(win));
            for(int i=1;i<=m;i++)
                win[i][0]=1;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {//cout<<"j="<<j<<" : ";
                    int len=1<<i;
                    int s=j/len;
                    if(j%len==0)
                        s--;
                    s*=len;//cout<<s+1<<"->"<<s+len<<" ";
                    int l=(j>(s+len/2)?(s+1):(s+len/2+1));
                    int r=(j>s+len/2?s+len/2:s+len);
                    //cout<<"l= "<<l<<" r="<<r<<" ";
                    for(int k=l;k<=r;k++)//第i轮第j个选手需要比较的区间
                    {
                        if(k==j)
                            continue;
                        win[j][i]+=win[j][i-1]*win[k][i-1]*p[j][k];
                    }
                    //cout<<win[j][i]<<endl;
                    if(i==n&&win[j][i]>maxn)
                    {
                        maxn=win[j][i];
                        num=j;
                    }
                }
            }//cout<<maxn<<endl;
            printf("%d
    ",num);
        }
        return 0;
    }
    
    
    

    3.Bag of mice CodeForces - 148D

    代码:
    【记忆化搜索】

    #include <bits/stdc++.h>
    using namespace std;
    double dp[1005][1005];//到达每个状态时的概率
    bool vis[1005][1005];//标记状态,避免重复搜索
    double dfs(int w,int b)//每次的状态对应的都是公主取的时刻
    {
        if(w<=0)//没有白色:输
            return 0;
        if(b<=0)//没有黑色:赢
            return 1;
        if(vis[w][b])
            return dp[w][b];
        vis[w][b]=1;
        double &res=dp[w][b];//下面w,b改变了
        res=1.0*w/(w+b);//或者取白色
        if(b>=2)//或者取黑色
        {
            double t=b*1.0/(w+b);//公主取黑色
            b--;
            t*=b*1.0/(w+b);//龙取黑色
            b--;
            res+=t*(w*1.0/(w+b)*dfs(w-1,b)+b*1.0/(w+b)*dfs(w,b-1));//白色跑或者黑色跑
        }
        return res;
    }
    int main()
    {
        int w,b;
        scanf("%d%d",&w,&b);
        printf("%.9f
    ",dfs(w,b));
        return 0;
    }
    
    

    【概率dp】
    对公主而言有两种选择:
      1.取白球,获胜;
      2.取黑球,取决于后面的情况;
    当选择黑球,为使公主获胜,龙必然选择黑球,那么跳出的球就有两种可能:白或黑
      白:(dp[i][j]=1.0*j/(i+j)*1.0*(j-1)/(i+j-1)*1.0*i/(i+j-2)*dp[i-1][j-2];)
      黑:(dp[i][j]=1.0*j/(i+j)*1.0*(j-1)/(i+j-1)*1.0*(j-2)/(i+j-2)*dp[i][j-3];)
    边界条件:
      全为白球:(dp[i][0]=1;)
      全为黑球:(dp[0][i]=0;)

    #include <bits/stdc++.h>
    using namespace std;
    double dp[1005][1005];
    int main()
    {
        int w,b;
        scanf("%d%d",&w,&b);
        for(int i=1;i<=w;i++)
            dp[i][0]=1;
        for(int i=1;i<=w;i++)
        {
            for(int j=1;j<=b;j++)
            {
                dp[i][j]=1.0*i/(i+j);//取白球
                double t=1.0*j/(i+j)*1.0*(j-1)/(i+j-1);//两者都取黑球
                if(j>=3)//跳白球
                    dp[i][j]+=t*1.0*(j-2)/(i+j-2)*dp[i][j-3];
                if(i>=1&&j>=2)//跳黑球
                    dp[i][j]+=t*1.0*i/(i+j-2)*dp[i-1][j-2];
            }
        }
        printf("%.9f
    ",dp[w][b]);
        return 0;
    }
    
    

    4.Check the difficulty of problems POJ - 2151

    分析:

    (dp[i][j][k]):表示第 (i) 个队在前 (j) 题中做对 (k) 道的概率;(记住这种表示方法)
    状态转移方程:(dp[i][j][k]=dp[i][j-1][k-1]*p[i][j]+dp[i][j-1][k]*(1-p[i][j]));
    边界条件:(dp[i][0][0]=1,dp[i][j][0]=prod_{k=1}^{j}{(1-p[i][k])})

    (s[i][j]):表示第 (i) 个队整场比赛中做出的题目数 (leq j) 的概率;
    (s[i][j]=sum_{k=0}^{j}{dp[i][m][k]})

    (P_1)表示每队至少做出一题的概率,(P_2)表示每队做出的题目数为 ([1,n-1]) 的概率;
    (P_1=prod_{i=1}^{t}{(1-s[i][0])})
    (P_2=prod_{i=1}^{t}{(s[i][n-1]-s[i][0])})

    最终结果为:(P_1-P_2),即所有队都至少做出一道题且至少有一个队做出了 (n) 道题。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=1005;
    double dp[N][32][32],s[N][32],p[N][32];
    int main()
    {
        int m,t,n;
        while(scanf("%d%d%d",&m,&t,&n),m||t||n)
        {
            for(int i=1;i<=t;i++)
                for(int j=1;j<=m;j++)
                    scanf("%lf",&p[i][j]);
            for(int i=1;i<=t;i++)
            {
                dp[i][0][0]=1.0;
                for(int j=1;j<=m;j++)
                {
                    dp[i][j][0]=dp[i][j-1][0]*(1-p[i][j]);
                    for(int k=1;k<=j;k++)
                        dp[i][j][k]=dp[i][j-1][k-1]*p[i][j]+dp[i][j-1][k]*(1-p[i][j]);
                }
            }
            for(int i=1;i<=t;i++)
            {
                for(int j=0;j<=m;j++)
                {
                    s[i][j]=0;
                    for(int k=0;k<=j;k++)
                        s[i][j]+=dp[i][m][k];
                }
            }
            double p1=1.0,p2=1;
            for(int i=1;i<=t;i++)
            {
                p1*=(1-s[i][0]);
                p2*=(s[i][n-1]-s[i][0]);
            }
            printf("%.3f
    ",p1-p2);
    
        }
        return 0;
    }
    
    
  • 相关阅读:
    使用node-inspector调试nodejs程序<nodejs>
    2015 2月记事(1)
    设置npm安装模块目录<nodejs>
    BZOJ 1965 [AHOI2005]洗牌
    BZOJ 1924 [Sdoi2010]所驼门王的宝藏
    【NOIP2003】传染病控制
    BZOJ [Scoi2015]情报传递
    [Noi2002]Savage
    BZOJ 4025: 二分图
    BZOJ 4999 This Problem Is Too Simple!
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/12377965.html
Copyright © 2011-2022 走看看