ZOJ 3329 One Person Game 【概率DP,求期望】

题意:有三个骰子,分别有k1,k2,k3个面。

每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和。

当分数大于n时结束。求游戏的期望步数。初始分数为0

 

设dp[i]表示达到i分时到达目标状态(即i = n)的期望,pk为投掷k分的概率,

p0为回到0的概率则dp[i] = ∑(pk * dp[i + k]) + dp[0] * p0 + 1 ;

都和dp[0]有关系,而且dp[0]就是我们所求,为常数设

  dp[i] = A[i] * dp[0] + B[i];

即为dp[i + k] = A[i + k] * dp[0] + B[i + k];

将其代入原式:dp[i] = ∑(pk * A[i + k] * dp[0] + pk * B[i + k]) + dp[0] * p0 + 1

          = (∑(pk * A[i + k]) + p0) * dp[0] + ∑(pk * B[i + k]) + 1;

所以可得:A[i] = ∑(pk * A[i + k]) + p0
        B[i] = ∑(pk * B[i + k]) + 1

先递推求得A[0]和B[0]。那么 dp[0] = B[0] / (1 - A[0]);

 

Source Code:

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler

#include <stdio.h>

#include <iostream>

#include <fstream>

#include <cstring>

#include <cmath>

#include <stack>

#include <string>

#include <map>

#include <set>

#include <list>

#include <queue>

#include <vector>

#include <algorithm>

#define Max(a,b) (((a) > (b)) ? (a) : (b))

#define Min(a,b) (((a) < (b)) ? (a) : (b))

#define Abs(x) (((x) > 0) ? (x) : (-(x)))

#define MOD 1000000007

#define pi acos(-1.0)



using namespace std;



typedef long long           ll      ;

typedef unsigned long long  ull     ;

typedef unsigned int        uint    ;

typedef unsigned char       uchar   ;



template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;}

template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;}



const double eps = 1e-7      ;

const int N = 210            ;

const int M = 1100011*2      ;

const ll P = 10000000097ll   ;

const int MAXN = 10900000    ;



int n, k1, k2, k3, ka, kb, kc;

double a[600], b[600], p[100];



int main(){

    std::ios::sync_with_stdio(false);

    int i, j, t, k, u, v, numCase = 0;

    cin >> t;

    while(t--){

        cin >> n >> k1 >> k2 >> k3 >> ka >> kb >> kc;

        memset(p, 0, sizeof(p));

        for(i = 1; i <= k1; ++i){

            for(j = 1; j <= k2; ++j){

                for(k = 1; k <= k3; ++k){

                    if(i == ka && j == kb && k == kc){

                        p[0] += 1.0 / (k1 * k2 * k3);

                        continue;

                    }

                    p[i + j + k] += 1.0 / (k1 * k2 * k3);

                }

            }

        }

        memset(a, 0, sizeof(a));

        memset(b, 0, sizeof(b));

        for(i = n; i >= 0; --i){

            a[i] = p[0];

            b[i] = 1.0;

            for(k = 1; k <= k1 + k2 + k3; ++k){

                a[i] += p[k] * a[i + k];

                b[i] += p[k] * b[i + k];

            }

        }

        printf("%.16f\n",b[0] / (1.0 - a[0]));

    }



    return 0;

}

 

你可能感兴趣的:(game)