837. New 21 Game DP + 概率

新21游戏是一道DP题,又是一道概率题
我刚开始从前往后算,结果TLE了。
我最初的思路是这样子:
对于每一层每一个可能的结果,
我看一下我每一步可能走出什么样的结果,把这些结果的概率乘以本层本位置的概率撒到下一层。
这样的时间复杂度是 N * N * W 的样子。

答案用的是从后往前看,对于一个状态,如果他的值在K到N之前,就是1。大于 N就是0
那如果我在K -1时,我就要抽一张. 如果我抽到 1 到 (N - K +1)之间就符合条件,所以
f(k - 1) = 1/W ( f(k - 1 + 1) + f(k - 1 + 2) + ... + f(k - 1 + W));
这样做的好处是不需要像我的做法那样分层去做了。层的概念天然溶合在计算过程中了。
这样的时间复杂度是 f(NW). 但仔细观察还可以得出 f(N)的优化。
总之这道题概率的成份大于DP的成份
dp的状态是从当前数值出发能有多大概率得到符合要求的数字。

看一下代码。

    public double new21Game(int N, int K, int W) {
        if (K == 0 || N >= K + W) return 1;
        double[] dp = new double[K + W + 1];
        
        for (int i = K; i <= K + W && i <= N; i++) dp[i] = 1.0;
        for (int i = K - 1; i >= 0; i--) {
            if (i + W > K - 1) { //还可以优化一下。
                for (int w = 1; w <= W; w++) {
                    dp[i] += dp[i + w] / W;
                }
            } else dp[i] = dp[i + 1] + dp[i + 1] / W - dp[i + W + 1] / W; 
        }
        return dp[0];
    }

你可能感兴趣的:(837. New 21 Game DP + 概率)