• 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
    ",b[0] / (1.0 - a[0]));
        }
    
        return 0;
    }
  • 相关阅读:
    Navicat使用技巧(附快捷键)
    Eclipse working set 快捷键
    行为模式--策略模式
    软件的可复用性和维护性
    外观模式
    建造者模式
    开闭原则
    迪米特法则
    工厂作业方法
    依赖倒置原则
  • 原文地址:https://www.cnblogs.com/wushuaiyi/p/4339942.html
Copyright © 2020-2023  润新知