您的位置:首页 > 其它

ZOJ - 3329 One Person Game(概率dp)

2014-11-01 18:35 465 查看
用d[ i ]表示点数和为 i 时还需要掷多少次筛子的期望,pk表示掷一次筛子和为 k 的概率。

d[ i ] = ∑ ( pk * d[ i + k ] ) + p0 * d[ 0 ] + 1;

d[ 0 ]是要求的常数.

令d[ i ] = a[ i ] * d[ 0 ] + b[ i ]

带入递推式中,得到

a[ i ] = p0 + ∑( pk * a[ i + k ] );

b[ i ] = 1 + ∑( pk * b[ i + k ]);

则d[ 0 ] = b[ 0 ] / ( 1 - a[ 0 ] );

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
using namespace std;

int k1, k2, k3, a, b, c, n;
int pk[20];
double p, A[600], B[600];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d%d%d%d%d%d", &n, &k1, &k2, &k3, &a, &b, &c);
        memset(pk, 0, sizeof(pk));
        p=1.0/(k1*k2*k3);
        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)
                        pk[i+j+k]++;
        memset(A, 0, sizeof(A));
        memset(B, 0, sizeof(B));

        for(int i=n; i>=0; i--)
        {
            A[i]=p;
            B[i]=1;
            for(int j=3; j<=k1+k2+k3; j++)
            {
                A[i]+=A[i+j]*pk[j]/(k1*k2*k3);
                B[i]+=B[i+j]*pk[j]/(k1*k2*k3);
            }
        }
        printf("%.16lf\n", B[0]/(1.0-A[0]));
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: