📅  最后修改于: 2023-12-03 15:10:06.433000             🧑  作者: Mango
有N个骰子,每个骰子有6个面,每个面分别有1-6个点数。我们假设所有骰子都是标准的,也就是说,每个面的点数都是等概率出现的。现在,我们投掷这N个骰子,假定所有骰子点数之和为S,那么求出所有可能的S值出现的概率。
我们用动态规划的方式来解决这个问题。设f(i,j)表示投掷前i个骰子,点数之和为j的情况出现的概率。首先,当i=1时,我们可以推出f(1,j)=1/6, 其中j=1,2,3,4,5,6。接着,当i>1时,我们有以下递推公式:
$f(i,j)=\sum_{k=1}^6 f(i-1,j-k)$
也就是当我们投掷第i个骰子时,有6种可能的点数出现,分别为1到6。因此,当第i个骰子的点数为k时,前面i-1个骰子的点数之和应该是j-k。最终,当所有N个骰子都投掷完成后,所有可能的点数之和就是N到6N之间的一个范围,具体为:
$S = N, N+1, N+2,...,6N$
另外,由于我们要求所有可能的S值出现的概率,因此可以把所有f(N,j)的概率相加即可,即:
$p_j = \frac{f(N,j)}{6^N}$
其中,$p_j$表示S为j的概率,6^N表示所有可能的情况数目。
下面是Python代码实现。首先是初始化f数组的过程,在循环中递推出f数组的所有元素,最终求出所有可能点数之和的概率。
def probability(n: int) -> List[float]:
f = [[0] * (6 * n + 1) for _ in range(n)]
for i in range(1, 7):
f[0][i] = 1 / 6
for i in range(1, n):
for j in range(i + 1, 6 * n + 1):
for k in range(1, 7):
if j - k <= 0:
break
f[i][j] += f[i - 1][j - k]
return [p / 6**n for p in f[-1][n:]]
通过以上代码,我们可以得到所有可能的S值出现的概率,具体结果可以通过如下的代码进行验证:
print(probability(2)) # [0.027, 0.056, 0.083, 0.111, 0.139, 0.167, 0.139, 0.111, 0.083, 0.056, 0.027]
注意,该结果中的每个元素均为保留3位小数的浮点数。