• ZOJ 3329:One Person Game 概率DP求期望(有环)


    One Person Game

    题目链接:

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3754

    题意:

    玩一个掷骰子的游戏,同时掷三个筛子,每次掷筛子都会得到分数(三个筛子掷得的数的合),规则如下:

                                                 初始分数为0,如果一号骰子掷得a且二号骰子掷得b,同时三号筛子掷得c,则分数归零

                                                当分数大于n时游戏结束

    求直到游戏结束掷骰子的次数的期望

    题解:

    设E[i]为初始分数为0时所求的期望,则E[n+1]=0,E[0]即所求答案

    可以知道 E[i]=∑(E[i+k]*p[k])+P0*E[0]+1 ,p[k]掷得三个骰子的得分合为k的概率,p0为归零的概率

    由于所有的E[i]都与E[0]有关,因此不能直接由这条公式得到答案

    可以将E[0]当做一个常数,设E[i]=a[i]*E[0]+b[i]

    则 E[i]=∑((a[i+k]*E[0]+b[i+k])*p[k])+P0*E[0]+1

    可得E[i]=(∑(Pk*a[i+k])+p0)*E[0]+∑(Pk*b[i+k])+1

    由此可知:

      a[i]=∑(Pk*a[i+k])+p0

      b[i]=∑(Pk*b[i+k])+1

    因为E[i>n]=0 所以E[i>n]=a[i>n]*E[0]+b[i>n]=0---->a[i>n]=b[i]>n=0

    由E[0]=a[0]*E[0]+b[0]

    可知  E[0]=(1-a[0])/b[0]

    注意:求p[k]时要注意归零的情况

                 

    代码

    #include<stdio.h>
    #include<string.h>
    double P[19],s[502],d[502],p0;
    int main()
    {
      int T,n,K1,K2,K3,a,b,c;
      scanf("%d",&T);
      while(T--)
      {
        scanf("%d%d%d%d%d%d%d",&n,&K1,&K2,&K3,&a,&b,&c);
        memset(P,0,sizeof(P));
        memset(s,0,sizeof(s));
        memset(d,0,sizeof(d));
        s[n+1]=d[n+1]=0.0;
        p0=1/(K1*K2*K3*1.0);
        for(int i=1;i<=K1;++i)
        for(int j=1;j<=K2;++j)
        for(int k=1;k<=K3;++k)
        if(i!=a||j!=b||k!=c)

        P[i+j+k]+=p0;

        for(int i=n;i>=0;--i)
        {
          for(int j=3;j<=K1+K2+K3;++j)
          if(i+j<=n+1)
          {
            s[i]+=s[i+j]*P[j];
            d[i]+=d[i+j]*P[j];
          }
          else break;
          s[i]+=p0,d[i]++;
        }
        printf("%.15f ",d[0]/(1.0-s[0]));
      }
    }

      

  • 相关阅读:
    【对拍√】
    hdu5791 TWO
    luogu P1220 关路灯
    【NOI2001】食物链
    【HAOI2016】食物链
    luogu P1006 传纸条
    可持久化平衡树
    可持久化并查集
    线段树合并(【POI2011】ROT-Tree Rotations)
    可持久化数组
  • 原文地址:https://www.cnblogs.com/kiuhghcsc/p/5565082.html
Copyright © 2020-2023  润新知