剑指 Offer 60. n个骰子的点数

剑指 Offer 60. n个骰子的点数

概率dp。
我们用\(dp[i][j]\)表示使用i个骰子投出总和j的概率,容易得到n个骰子最大的和为\(6 \times n\),即全为6的情况,范围在[n, 6n]之间,共计有\(5 \times n + 1\)种情况。
如果暴力求解,那么范围就会在\(6 ^ n\)之间,肯定会造成超时。

但是需要注意的是\(x - i\)会有越界问题,如求\(f(2,2)\)时,就只需要求\(f(1,1)\)即可,因为\(f(1,0),f(1,-1)\)都没有意义。

class Solution {
    public double[] dicesProbability(int n) {
        double[] res = new double[5 * n + 1];
        // n个骰子投出s的概率
        int[][] dp = new int[n + 1][n * 6 + 1];
        double all = Math.pow(6, n);
        for(int i = 1; i <= 6; i++) {
            dp[1][i] = 1;
        }
        // 枚举n个骰子
        for(int i = 1; i <= n; i++) {
            // 枚举这么n个骰子时所有可能的和
            for(int j = i; j <= 6 * i; j++) {
                // 每一步都可以从上一步的j - k得到
                for(int k = 1; k <= 6; k++) {
                    dp[i][j] += j > k ? dp[i - 1][j - k] : 0;
                    if(i == n) {
                        res[j - i] = dp[i][j] / all;
                    }
                }
            }
        }
        return res;
    }
}
posted @ 2022-02-12 21:45  NullPointer_C  阅读(55)  评论(0)    收藏  举报