• 期望dp专题


    期望什么的没什么大概印象

    靠做题一步一步来吧

    先一道水题

     Kids and Prizes

    题意:n个盒子里装有礼物,m个人随机选择礼物,选完之后空盒子放回
    问选中的礼物数的期望。
    m个人是独立的。
    对于每个礼物不被人选中的概率为((n-1)/n)^m
    那么不被选中的礼物数的期望就是 n*((n-1)/n)^m
    所以答案就是 n-n*((n-1)/n)^m;

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int n,m;
    double pow(double x,int y)
    {
        int i;
        double sum=1;
        for(i=1;i<=y;i++)
          sum*=x;
        return sum;
    }
    int main()
    {
        double cnt;
         double ans;
        while(~scanf("%d%d",&n,&m))
        {
         cnt=double(n-1)/n;
        ans=n-n*pow(cnt,m);
        printf("%.9lf
    ",ans);
        }
        return 0;
    }
    

      

    SPOJ1026 Favorite Dice

    题目大意

    给你一个n个面的骰子,每个面朝上的几率相等,问每个面都被甩到的期望次数

    题解

    当然也可以用概率dp来推:

    我们设f[i]表示还须i种数才满足每个面都出现一次所需要的期望次数。

    显然f[n]=0,答案为f[0],所以为逆推。

    又由于选第i个数后再选一个数与已经选过的数不同的概率为(ni)/n,相同为i/n

    故f【i】=(f【i+1】+1)*((n-i)/n)【就是成功选出不同的,那就加1次再乘上概率】+(f【i】+1)*(i/n)【这个就是本身的转了一次没拿到不同的,同样是+1乘上概率】

    化简可得到f[i] = f [i + 1] + n/(n - i);
    同时f【n】=0;所以代码
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int t;
    double f[1005];
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            memset(f,0,sizeof(f));
            f[n] = 0;
            for(int i = n - 1;i >= 0;i--)
            {
                f[i] = f[i + 1] + n / (n - (double)i);
            }
            printf("%0.2lf
    ",f[0]);
         } 
         return 0;
    }

    Uva12230Crossing Rivers (数学期望)

    题目大意:
    有个人每天要去公司上班,每次会经过N条河,家和公司的距离为D,默认在陆地的速度为1,
    给出N条河的信息,包括起始坐标p,宽度L,以及船的速度v。船会往返在河的两岸,人到达河岸时,
    船的位置是随机的(往返中)。问说人达到公司所需要的期望时间。
    思路:
    
    1,过每条河最坏的情况是t=3*L/v; 即去的时候船刚刚走。
    2,过没条河最优的情况是t=L/v;    即去的时候船刚刚来。
    3,由于船是均匀发布的,符合线性性质,所以平均下来,过每条河的时间t=2*L/v。
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    using namespace std;
    int main()
    {
        int n,D,dis,p,l,v,Case=0;
        double ans;
        while(~scanf("%d%d",&n,&D)){
            if(n==0&&D==0) return 0;
            dis=0;ans=0;
            while(n--){
                scanf("%d%d%d",&p,&l,&v);
                ans=ans+2.0*l/v;
                D-=l;
            }
            ans=ans+1.0*D;
            printf("Case %d: %.3lf
    
    ",++Case,ans);
        }
        return 0;
    }
    

     codeforces round 604 E题:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxx = 2e5+10;
    const int mod = 998244353;
    LL p[maxx],dp[maxx];
    LL quick(LL a,LL b)
    {
        LL res=1;
        while(b)
        {
            if(b&1)res=(res*a)%mod;
            b>>=1;
            a=(a*a)%mod;
        }
        return res;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&p[i]);
        //dp[i]=(dp[i-1]+1)*(pi/100)+(dp[i-1]+1+dp[i])*(1-pi/100)
        for(int i=1;i<=n;i++)
            dp[i]=(dp[i-1]+1)*100%mod*quick(p[i],mod-2)%mod;
        printf("%lld
    ",dp[n]);
        return 0;
    }
    

      help me escape

    题意:

    师傅被妖怪抓走了。有n个妖怪,每个妖怪有一个固定的战斗力c[],师傅也有一个初始战斗力f0。每天,师傅会随机选择一个妖怪决斗,如果打得赢ft>c[],就可以逃出去,逃出去要t[]天,毕竟超人不会飞;否则,师傅会不甘心,当天他会拿出秘籍练功,将自己变强,f(t+1)=f(t)+c[],第二天寻找下一次机会。问师傅能够逃脱可怕的妖怪,继续追求去印度吃手抓饼的梦想的天数的数学期望day。

    思路:

    设dp[F]是战斗力为F时,逃离的天数期望。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const double P=(1.0+sqrt(5.0))/2.0;
    const int maxn=200000;
    int c[maxn],t[maxn],n,f;double dp[maxn];
    double dfs(int F)
    {
        if(dp[F]>0) return dp[F];
         for(int i=1;i<=n;i++){
            if(F>c[i]) dp[F]+=1.0*t[i];
            else dp[F]+=dfs(F+c[i])+1.0;
        }
        dp[F]=dp[F]/(1.0*n);return dp[F];
    }
    int main()
    {
        while(~scanf("%d%d",&n,&f)){
           memset(dp,0,sizeof(dp));
           for(int i=1;i<=n;i++){
                scanf("%d",&c[i]);
                t[i]=(int)(1.0*c[i]*c[i]*P);
           }dfs(f);
           printf("%.3lf
    ",dp[f]);
       }return 0;
    }
    

      

    HDU3853LOOPS (师傅逃亡系列•三)(基础概率DP)

    要你从f【0】【0】到f【n】【m】,每次操做都要消耗两颗·神丹,有a的概率原地不动,b的概率向右走,有c的概率向下走。求师傅逃出去的神丹消耗期望。

    思路:

    依然是递推,

    设f[i][j]为从(i,j)点走到终点所花费的期望,a[i][j],b[i][j],c[i][j]分别是留在原地、向右走、向下走的概率,则可以得到:

    f[i][j]=a[i][j]*f[i][j]+b[i][j]*f[i][j+1]+c[i][j]*f[i+1][j]+2

    移项得: dp[i][j]=(dp[i][j+1]*b[i][j]+dp[i+1][j]*c[i][j]+2)/(1.0-a[i][j]

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    double dp[1010][1010],a[1010][1010][3];
    int main()
    {
        int n,m,i,j,k;
        while(~scanf("%d%d",&n,&m)){
            for(i=1;i<=n;i++)
             for(j=1;j<=m;j++)
              for(k=0;k<3;k++)
               scanf("%lf",&a[i][j][k]);
            memset(dp,0,sizeof(dp));
            for(i=n;i>=1;i--) 
             for(j=m;j>=1;j--)
             {
                  if(fabs(1-a[i][j][0])<1e-7)//停留原地的概率为1  
                        continue;  
                 dp[i][j]=(dp[i][j+1]*a[i][j][1]+dp[i+1][j]*a[i][j][2]+2)/(1.0-a[i][j][0]); 
             }
            printf("%.3f
    ",dp[1][1]);
        }return 0;
    }
    

      

    ); 

    ZOJ 3551 Bloodsucker

    题意:
    开始有 n-1个人,1个吸血鬼,以后每天这 n 个中其中有两个会相遇,如果一个是吸血鬼,一个是人,那这个人有一定的概率 p 变成吸血鬼。

    求这 n 个最后都变成吸血鬼所需天数的期望值。

    思路:
    我们设dp【i】为吸血为i个的时候的天数期望

    那么dp【n】=0;dp【1】为我们所求的。

    然后就会有dp【i】=(dp【i+1】+1)*p3+(dp【i】+1)*(1-p3);

    移项:dp[i] = (dp[i+1]*p3+1)/p3;

    #include <cstdio>
    #include <cstring>
    double dp[100017];
    int main()
    {
        int t, n;
        double p;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%lf",&n,&p);
            dp[n] = 0;
            double p1 = (double)n*(n-1)/2;//c n 2 n个人中选2人
            for(int i = n-1; i >= 1; i--)
            {
                double p2 = (double)i*(n-i);
                double p3 = p2/p1*p;//相遇并变成吸血鬼的概率
                dp[i] = (dp[i+1]*p3+1)/p3;
            }
            printf("%.3lf
    ",dp[1]); 
        }
        return 0;
    }
    

      

  • 相关阅读:
    Python字符串学习
    文本压缩版本三
    文件压缩版本二
    文件压缩(2)
    d17包,logging模块,hashlib模块 openpyxl模块,深浅拷贝
    d16 collections模块 时间模块 random模块 os模块 sys模块 序列化模块 subprocess模块
    d15 常用模块之正则模块
    14天 模块 , 导模块 , 循环导入, 相对,绝对导入, 项目目录规范,
    13t天 迭代器,生成器,内置函数
    55 jquery
  • 原文地址:https://www.cnblogs.com/hgangang/p/12005866.html
Copyright © 2020-2023  润新知