标签:
有三个分别有K1,K2,K3个面的骰子,每个面上的值为[1,Ki]
设所投出的序列为{k1,k2,k3}
当投出{a,b,c}时得分清零,否则得分增加k1+k2+k3
求使得得分大于等于n的期望步数
设dp[i]表示当前得分为i,达成目标所需的期望步数
dp[i]=dp[i+k]*p[k]+dp[0]*p0+1
其中p[i]表示使得分增加i的概率
由于dp[i]与dp[0]有关,然而dp[0]未知,所以我们把dp[0]提出来
则dp[i]=A[i]*dp[0]+B[i]
带入原式得
dp[i]=(A[i+k]*dp[0]+B[i+k])*p[k]+dp[0]*p0+1
=A[i+k]*dp[0]*p[k]+B[i+k]*p[k]+dp[0]*p0+1
=dp[0]*(A[i+k]*p[k]+p0)+(B[i+k]*p[k]+1)
所以A[i]=A[i+k]*p[k]+p0,B[i]=B[i+k]*p[k]+1
边界:对于所有i>n,A[i]=B[i]=0
ans=dp[0]=B[0]/(1-A[0])
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 600 4 int T,n,K1,K2,K3,a,b,c; 5 double p0,A[maxn],B[maxn],p[maxn]; 6 void PP(){ 7 p0=1.0/(K1*K2*K3); 8 for(int i=1;i<=K1;i++) 9 for(int j=1;j<=K2;j++) 10 for(int k=1;k<=K3;k++){ 11 if(i==a&&j==b&&k==c)continue; 12 p[i+j+k]+=p0; 13 } 14 } 15 int main(){ 16 scanf("%d",&T); 17 while(T--){ 18 scanf("%d",&n); 19 scanf("%d%d%d",&K1,&K2,&K3); 20 scanf("%d%d%d",&a,&b,&c); 21 PP(); 22 memset(A,0,sizeof(A)); 23 memset(B,0,sizeof(B)); 24 for(int i=n;i>=0;i--){ 25 A[i]=p0,B[i]=1; 26 for(int j=3;j<=K1+K2+K3;j++){ 27 A[i]+=p[j]*A[i+j]; 28 B[i]+=p[j]*B[i+j]; 29 } 30 } 31 printf("%.15lf\n",B[0]/(1-A[0])); 32 } 33 return 0; 34 }
标签:
原文地址:http://www.cnblogs.com/Ngshily/p/5519556.html