题目:
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
思路:动态规划。
详细可参考:力扣
个人理解:
1.首先对于两个骰子,可以用两个for循环算,第一层for为第一个骰子,第二层for为第二个骰子。
2.当有n个骰子时候,同样可以用两个for,第一层for为前n-1个骰子和的取值范围,第二层for为当前骰子的范围,即[1,2,3,4,5,6]。也可以理解为,有一个1~6的骰子,还有一个数字为n~6n的骰子,问这两个骰子和的概率。
3.以此类推,n从2到某个数,不断计算保存的取值概率。
4.最重要的是,要保存每个骰子掷出时候的结果;同时,对于n个骰子,和的取值范围为:
[n , 6*n],因此,和的长度为:6*n-n+ 1 = 5n+1。
代码:
class Solution:
def func(self , n ):
res = [1/6] * 6 # 对于第一个骰子,结果已知,全为1/6
for ni in range(2 , n+1): # 从第二个骰子,到第n个骰子,不断计算
tmp = [0] * (5*ni +1) # 定义当前ni个骰子,和的取值范围,初始化为0
for j in range(len(res)): # 第一个掷骰子(从上一轮)和的范围,每个位置的值为和的概率
for k in range(6): # 第二个骰子(当前轮)的范围,即1,2,3,4,5,6 ,每个数字出现的概率均为1/6
tmp[j + k] += res[j] * (1/6) # j,k分别各自取值,j+k的和可以用多种j、k取值方式。res[j] * (1/6),表示,上一个骰子出现j的时候概率*这个骰子
# 的概率,此骰子出现每个数的概率均为1/6,以此类推。
res = tmp
return res
动态规划的主要目的是为了避免重复计算,既然每次掷骰子都会出现1~6的情况,且概率均为1/6,那么直接保存前面所有掷骰子出现的情况。