zoukankan      html  css  js  c++  java
  • 【ZOJ3329】One Person Game

    题目描述

    有三个骰子,分别有K1,K2,K3个面,一次投掷可以得到三个骰子点数加和的分数,但是,当骰子1等于A,骰子2=B,骰子3=C时,结果清零。问从0开始,分数超过N时投掷次数的期望。


    输入

    第一行一个数T,表示数据组数。

    每组数据对应一行7个数,分别为N,K1,K2,K3,A,B,C (0 <= n <= 500, 1 < K1, K2, K3 <= 6, 1 <= A <= K1, 1 <= B <= K2, 1 <= C <= K3).。


    输出

    T行,对应每组数据的期望,保留15位小数。


    样例输入

    2
    0 2 2 2 1 1 1
    0 6 6 6 1 1 1


    样例输出

    1.142857142857143
    1.004651162790698



    题解

    本蒟蒻觉得这道题好难啊。

    首先,很容易想到设 dp[ i ] 表示当前点数是 i ,还需要投掷次数的期望。于是 dp[ i ] = Σ dp[ i+k ]*p[ k ] +dp[ 0 ]*p[ 0 ] + 1 ,其中 p[ k ] 表示投掷点数和为 k 的概率,特殊的,p[ 0 ] 为投到 a+b+c 的概率 (所以p[ a+b+c ] = 0 )。

    那么接下来怎么做呢,我们发现,dp[ i ] 可以表示为一个与 dp[ 0 ] 有关的式子和一个其他式子的和 ,于是设 dp[ i ] = A[ i ] * dp[ 0 ] + B[ i ] ---------- ①,带入上述方程可得:

                                                         dp[ i ] = Σ( A[ i+k ] * dp[ 0 ] * p[ k ] + B[ i+k ] * p[ k ] ) +dp[ 0 ] * p[ 0 ] + 1

                                打开变形:                 dp[ i ] = ( ΣA[ i+k ] * p[ k ] + p[ 0 ] ) * dp[ 0 ] + Σ B[ i+k ] * p[ k ] +1    ----------- ②

    我们比较①式和②式,得到:   A[ i ] = Σ A[ i+k ] * p[ k ] + p[ 0 ] , B[ i ] = Σ B[ i+k ] * p[ k ] + 1  。

    A[ i ] 和 B[ i ] 可以在O(n*k) 的时间内递推 。 算出 A[ 0 ] 和 B[ 0 ] ,带入 ①式 可得:  dp[ 0 ] = A[ 0 ] * dp[ 0 ] + B[ 0 ] 。

    移项化简:   dp[ 0 ] = B[ 0 ] / ( 1 - A[ 0 ] )

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=500+500+100;
    
    int T,a,b,c,k1,k2,k3,n;
    double A[maxn],B[maxn],dp[maxn],p[maxn];
    
    template<typename T>void read(T& aa){
        char cc; ll ff;aa=0;cc=getchar();ff=1;
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        aa*=ff;
    }
    
    int main(){
        read(T);
        while(T--){
            memset(dp,0,sizeof(0));
            memset(A,0,sizeof(A));
            memset(B,0,sizeof(B));
            memset(p,0,sizeof(p));
            read(n),read(k1),read(k2),read(k3),read(a),read(b),read(c);
            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.0/(k1*k2*k3);
            for(int i=n;i>=0;i--){
                for(int j=3;j<=k1+k2+k3;j++) A[i]+=A[i+j]*p[j],B[i]+=B[i+j]*p[j];
                A[i]+=1.0/(k1*k2*k3);B[i]+=1;
            }
            printf("%.15lf
    ",B[0]/(1.0-A[0]));
        }
        return 0;
    }
  • 相关阅读:
    SQL盲注攻击的简单介绍
    xss编码小结
    XssEncode
    xss payload
    2014年八大信息安全峰会演讲
    xss bypass
    移动APP安全在渗透测试中的应用
    WAF实现扫描器识别
    thinkphp的系统变量
    thinkphp AOP(面向切面编程)钩子和行为
  • 原文地址:https://www.cnblogs.com/rlddd/p/9490096.html
Copyright © 2011-2022 走看看