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

dp三步走:

1.表示状态

dp[i][j]表示掷i个骰子,点数之和为j的概率。

2.状态转移方程

递推公式dp[i][j]=dp[i-1][j-1]+……+dp[i-1][j-6]

i个骰子和为j的概率 = i-1个骰子和为j-1  *  最后一个骰子掷出1的概率 +……+ i-1个骰子和为j-6 * 最后一个骰子掷出6的概率

3.边界处理

i=1时,概率均为1/6

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

class Solution {
    public double[] dicesProbability(int n) {

        //dp[i][j]表示掷i个骰子,点数之和为j的概率
        double[][] dp = new double[n + 1][6 * n + 1];
        //边界问题,掷1个骰子得到1-6概率均为6分之一
        for(int i = 1; i <= 6; i++)
            dp[1][i] = (double)1 / 6;
        //从掷两个骰子开始递推
        for(int i = 2; i <= n; i++)
            //i个骰子点数之和的范围是i~6*i
            for(int j = i; j <= 6 * i; j++)
                //递推公式dp[i][j]=dp[i-1][j-1]+……+dp[i-1][j-6]
                //i个骰子和为j的概率 = i-1个骰子和为j-1 * 最后一个骰子掷出1的概率+……+i-1个骰子和为j-6 * 最后一个骰子掷出6的概率
                for(int k = 1; k <= 6; k++){
                    //边界问题,下面的j-k不能越界
                    if(j - k <= 0)
                        continue;
                    dp[i][j] += dp[i - 1][j - k] / 6;
                }
        //一共能掷出5*n+1个点数和
        double[] res = new double[5 * n + 1];
        int sum = n;
        //在循环赋值中写sum++,可以合并成1句
        for(int i = 0; i < res.length; i++)
            res[i] = dp[n][sum++];
        return res;
    }
}

 

posted @ 2021-03-27 19:28  星予  阅读(57)  评论(0编辑  收藏  举报