leetcode剑指offer 面试题60. n个骰子的点数

题干:
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。

示例 1:
输入: 1
输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]

示例 2:
输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]

限制:
1 <= n <= 11

解题思路:
1.可能值得概率 = 值出现得次数 / 总次数;总次数 = pow(6, n)
2.申请一个二维数组dp[ i ][ j ] 表示 i 个骰子出现得值得总和 j 出现得次数
状态转移方程:一共n个骰子,最后一个骰子掷完后,用dp[ n ][ j ]表示n个骰子掷出得 j 的次数,则n - 1枚骰子掷出后其对应的点数可以表示为 j - 1, j - 2, j - 3…j - 6,于是,有:

for (i = 1; i <= 6; i++){
     
	dp[n][j] += dp[n - 1][j - i];
}

3.需要注意的是,每多一个骰子,就会有一个值不可能出现,比如,两个骰子的和不可能出现1,至少是2.

代码实现:

double* twoSum(int n, int* returnSize){
     
    int i, j, k;
    int len = 5 * n + 1;
    * returnSize = len;
    double* res = (double*)malloc(sizeof(double) * len);
    int dp[12][67] = {
     0};                //申请一个二维数组存放投掷完n枚骰子后点数j出现的次数
    for (i = 1; i <= 6; i++){
                        //只有一个骰子时各点数出现的次数
        dp[1][i] = 1;
    }
    for (i = 2; i <= n; i++){
                        //当骰子数大于等于2时
        for (j = i; j <= 6 * i; j++){
                //可能出现的数字的个数
            for (k = 1; k <= 6; k++){
                //第n个骰子出现6种点数
                if (j - k <= 0){
     
                    break;
                }
                //当第n枚骰子点数为k时,它与前n-1个骰子的点数和所出现的次数
                dp[i][j] += dp[i - 1][j - k];   
            }
        }
    }
    int all = pow(6, n);
    for (i = 0; i < len; i++){
     
        res[i] = dp[n][n + i] * 1.0 / all;
    }
    return res;
}

你可能感兴趣的:(LeetCode,数据结构,算法,leetcode,c语言)