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\n",d[0]/(1.0-s[0]));
}
}