看了这么多,也就是个递推
1 /* 2 ZOJ 3329 3 题意:有三个骰子,分别有k1,k2,k3个面。 4 每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和。 5 当分数大于n时结束。求游戏的期望步数。初始分数为0 6 7 设dp[i]表示达到i分时到达目标状态的期望,pk为投掷k分的概率,p0为回到0的概率 8 则dp[i]=∑(pk*dp[i+k])+dp[0]*p0+1; 9 都和dp[0]有关系,而且dp[0]就是我们所求,为常数 10 设dp[i]=A[i]*dp[0]+B[i]; 11 代入上述方程右边得到: 12 dp[i]=∑(pk*A[i+k]*dp[0]+pk*B[i+k])+dp[0]*p0+1 13 =(∑(pk*A[i+k])+p0)dp[0]+∑(pk*B[i+k])+1; 14 明显A[i]=(∑(pk*A[i+k])+p0) 15 B[i]=∑(pk*B[i+k])+1 16 先递推求得A[0]和B[0]. 17 那么 dp[0]=B[0]/(1-A[0]); 18 */ 19 #include<stdio.h> 20 #include<string.h> 21 #include<iostream> 22 #include<algorithm> 23 using namespace std; 24 25 double A[600],B[600]; 26 double p[100]; 27 int main() 28 { 29 int T; 30 int k1,k2,k3,a,b,c; 31 int n; 32 scanf("%d",&T); 33 while(T--) 34 { 35 scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c); 36 double p0=1.0/k1/k2/k3; 37 memset(p,0,sizeof(p)); 38 for(int i=1;i<=k1;i++) 39 for(int j=1;j<=k2;j++) 40 for(int k=1;k<=k3;k++) 41 if(i!=a||j!=b||k!=c) 42 p[i+j+k]+=p0; 43 memset(A,0,sizeof(A)); 44 memset(B,0,sizeof(B)); 45 for(int i=n;i>=0;i--) 46 { 47 A[i]=p0;B[i]=1; 48 for(int j=1;j<=k1+k2+k3;j++) 49 { 50 A[i]+=A[i+j]*p[j]; 51 B[i]+=B[i+j]*p[j]; 52 } 53 } 54 printf("%.16lf\n",B[0]/(1-A[0])); 55 } 56 return 0; 57 }
时间: 2024-10-14 01:08:32