剑指offer python版博客
https://blog.csdn.net/sqiu_11/article/details/77657840
python版本答案
https://blog.csdn.net/shiquxinkong/article/details/37620421
解析:
http://www.voidcn.com/article/p-fpsyypkx-pk.html
注意细节:
dp1 = [0] * (n * dmax+1)
为什么是n*dmax+1呢,因为定义的,第i个色子,下标是从i开始,而不是从i-1开始。
df的第一个位置df[0]是没有意义的
我们可以考虑用两个数组来存储骰子点数的每一个总数出现的次数。在一次循环中, 第一个数组中的第n 个数字表示骰子和为n 出现的次数。在下一循环中,我们加上一个新的骰子,此时和为n 的骰子出现的次数应该等于上一次循环中骰子点数和为n-1 、n-2 、n-3 、n-4, n-5 与n-6 的次数的总和,所以我们把另一个数组的第n个数字设为前一个数组对应的第n-1 、n-2 、n-3 、n-4、n-5与n-6之和。
通过两个数组来回引用并处理的方式来进行逐渐的点数增加,注意最后都是落在点数上面,然后再根据点数得到概率,
"n是总共的色子数,s是给出的和,dmax是每个色子的最大点数,dmin是每个色子的最小点数" def dp_probability(n, s, dmax=6, dmin=1): if s < n * dmin or s > n * dmax: "当给出的和小于n(最小值),或者大于n*dmax(最大值)时,不符合条件,返回0" return 0 "定义出来一个df1s数组" dp1 = [0] * (n * dmax + 1) # init dp[1, :] "当只有一个色子时,每个点数出先的次数都是1,所以初始化为dp1[i]=1" for i in range(1, dmax + 1): dp1[i] = 1 # i: the number of dices "从第二个色子开始循环," for i in range(2, n + 1): dp2 = [0] * (n * dmax + 1) # j: range of i dices "色子数为i时,总共能出现的sum的情况(从dim*n到dmax*n)" for j in range(dmin * i, dmax * i + 1): # k: range of new added dice for k in range(dmin, dmax + 1): if j > k: "等于一次循环中,j-1,j-2...j-dmax的情况 之和,dp1为上一次情况" dp2[j] += dp1[j - k] print(dp2) dp1 = dp2 print("total = {0}, prob = {1}%".format(dp2[s], dp2[s] * 100 / dmax ** n)) return dp2[s] if __name__ == "__main__": result=dp_probability(5, 10, dmax=6, dmin=1)