One Person Game ZOJ - 3329(期望)

题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3329
思路:设maxn=k1+k2+k3,那么摇一次骰子的点数在3-maxn之间,p[i]表示骰子的点数为i的概率(不含第一,二,三个的骰子点数分别为a,b,c此时会清空),清空的概率p0=1/k1/k2/k3.
f[i]为当前骰子总点数为i到点数大于n的期望次数,初始时i=0,当i>n时,f[i]=0.
  k=maxn
f[i]=(∑ f[i+k]* p[k])+p0*f[0]+1①
  k=3
每次都有f[0]是一个循环,无法正常递推求解。
我们设f[i]=A[i]f[0]+B[i]
f[i+k]=A[i+k]*f[0]+B[i]③
将3式代入1式得,f[i]=(∑A[i+k]*p[k]+p0)*f[0]+∑B[i+k]*p[k]+1
因此我们发现A[i]=∑A[i+k] * p[k]+p0 B[i]=∑B[i+k] * p[k]+1
在当i>n时,f[i]=0.,那么A[i]=B[i]=0
所以我们从n一直递推到1求A[i],B[i]即可。
f[0]=A[0]*f[0]+B[0]
f[0]=B[0]/(1-A[0])

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>

using namespace std;

double A[506],B[506],p[20];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,k1,k2,k3,a,b,c;
        scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
        double p0;
        p0=1.0/(k1*k2*k3);
        memset(p,0,sizeof(p));
        for(int i=1;i<=k1;i++)
           {
               for(int j=1;j<=k2;j++)
               {
                   for(int k=1;k<=k3;k++)
                   {
                       int x=i+j+k;
                       p[x]+=p0;
                   }
               }
           }
           int x=a+b+c;
           p[x]-=p0;
           x=k1+k2+k3;
           /*for(int i=1;i<=x;i++)
           {
               printf("%lf\n",p[i]);
           }*/

           for(int i=n;i>=0;i--)
           {
               A[i]=p0; B[i]=1;
               for(int j=3;j<=x;j++)
               {

                   int x1=i+j;
                   if(x1>n);
                   else
                   {
                       A[i]+=p[j]*A[x1];
                       B[i]+=p[j]*B[x1];
                   }

               }
           }
           double ans=B[0]/(1-A[0]);
           printf("%.15lf\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值