ZOJ 3329 One Person Game 概率DP 期望 难度:2

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3754

本题分数为0的概率不确定,所以不能从0这端出发.

设E[i]为到达成功所需的步数,明显i>n时E[i]=0,当0<i<=n时E[i]=sigma(E[i+k]*pk)+E[0]*p0,(k是可以投出的除了恰为a,b,c以外的骰子之和),

在这个公式里,E[i]和E[0]都是未知的,设E[0]=x,则

E[i]=sigma(E[i+k]*pk)+x*p0+1,

因为比i大的所有j,满足E[j]的一次项和零次项都是已知的,明显,可以用x来表示所有E[i],

设E[i]的一次项部分为a[i],常数项部分为b[i],逐渐递推,可以得到E[0]=a[0]*E[0]+b[0],这时E[0]可解出,即为答案

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=505;
const int maxk=7;
double p[maxk*3],dpa[maxn],dpb[maxn];
int n,k1,k2,k3,a,b,c;
int sumk;
double mulk;
void init(){
        sumk=k1+k2+k3;
        mulk=k1*k2*k3;
        memset(p,0,sizeof(p));
        p[0]=1/mulk;
        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]+=1/(mulk);}

                }
            }
        }
}
void calc(){
    for(int i=n;i>=0;i--){
        dpa[i]=p[0];
        dpb[i]=1;
        for(int j=3;j<=sumk&&i+j<=n;j++){
            dpa[i]+=dpa[i+j]*p[j];
            dpb[i]+=dpb[i+j]*p[j];
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int ti=1; ti<=T; ti++)
    {
        scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
        init();
        calc();
        printf("%.15f
",dpb[0]/(1-dpa[0]));
    }

    return 0;
}
原文地址:https://www.cnblogs.com/xuesu/p/4478517.html