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]));
  }
}

  

原文地址:https://www.cnblogs.com/kiuhghcsc/p/5565082.html