Leetcode刷题:剑指offer【面试题60 n个骰子的点数】

【面试题60 n个骰子的点数】

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

思路:动态规划。可以考虑用一个二维数组存储 dp 状态,行 i 表示当前已经掷了 i 个骰子,列 j 表示骰子的点数和,dp[i][j] 表示当前有 i 个骰子,有 dp[i][j] 种组合方式得到点数和 j。对于 n 个骰子,掷法组合是 6 n 6^n 6n 种,所以最后返回的结果就是 dp 数组最后一行(n个骰子)不为 0 的结果除以 6 n 6^n 6n,即概率值。

  • 明确状态:唯一的变量当前骰子的个数下,掷法的数量
  • dp 数组dp[i][j] 表示当前有 i 个骰子,有 dp[i][j] 种组合方式得到点数和 j
  • 明确选择:假设当前有 i 个骰子,要组合出点数 j,可以看作是 i-1 个骰子再加上一个点数(1~6),即 dp[i][j] 可以由 dp[i-1][j-1]dp[i-1][j-2]…、dp[i-1][j-6] 的累加和得来。
  • 状态间转移关系:根据上面分析可知,dp[i][j] += dp[i-1][j-cur],其中 cur 的范围是 1 ~ 6
  • 确定 base case:当 i 等于 1 时,即只有 1 个骰子,j = 1 ~ 6 的掷法都是 1
class Solution:
    def twoSum(self, n: int):
        dp = [[0]*(6*n+1) for _ in range(n+1)]
        res = []
        for i in range(1,7):
            dp[1][i] = 1
        for i in range(1, n+1):   # 骰子个数
            for j in range(i, 6*n+1):   # 点数
                for cur in range(1,7):
                    dp[i][j] += dp[i-1][j-cur]
        sum = pow(6, n)
        for i in range(6*n+1):
            if dp[n][i] != 0:
                res.append(dp[n][i] / sum)
        return res

你可能感兴趣的:(今天刷题了吗)