題目描述:
扔 n 個骰子,向上面的數字之和為 S。給定 Given n,請列出所有可能的 S 值及其相應的概率。
注意事項
You do not care about the accuracy of the result, we will help you to output results.
給定 n = 1
,返回 [ [1, 0.17], [2, 0.17], [3, 0.17], [4, 0.17], [5, 0.17], [6, 0.17]]
。
題目分析:
題目:You do not care about the accuracy of the result, we will help you to output results.
開始還自己處理浮點數,結果題目有說不用處理。。。
題目:把n個骰子扔在地上,所有骰子朝上一面的點數之和為S。輸入n,打印出S的所有可能的值出現的概率。
1.假設在n個骰子和點數和Sum的情況下,次數m = f(n,Sum)
2.當然n-1塊骰子的情況下,一般情況下可投出Sum-1、Sum-2、Sum-3、Sum-4、Sum-5、Sum-6的情況,即留給最后一塊骰子1-6的投擲空間;
(k-1,n-1):第k個骰子投了點數1
(k-1,n-2):第k個骰子投了點數2
(k-1,n-3):第k個骰子投了點數3
....
(k-1,n-6):第k個骰子投了點數6
AllPro = f(n,Sum) = f(n-1,Sum-1) + f(n-1,Sum-2) + f(n-1,Sum-3) + f(n-1,Sum-4) + f(n-1,Sum-5) + f(n-1,Sum-6)
3.特殊情況一,Sum - i < 1 *(n-1),即留給n-1塊骰子的投擲空間已經比n-1塊骰子的最小點數和還小了!
AllPro = f(n,Sum) = f(n-1,Sum-i) + f(n-1,Sum-i-1) + ... + f(n-1,Sum-5) + f(n-1,Sum-6)
4.特殊情況二,Sum - i > 6 *(n-1),即留給n-1塊骰子的投擲空間已經比n-1塊骰子的最大點數和還大了!
AllPro = f(n,Sum) = f(n-1,Sum-1) + f(n-1,Sum-2) + ... + f(n-1,Sum-i) + f(n-1,Sum-i-1)
例如 n = 1時:
f(1,1) = f(1,2) = f(1,3) = f(1,4) = f(1,5) = f(1,6) = 1
而 n = 2時:
f(2,2) = f(1,1) = 1
f(2,3) = f(1,2) + f(1,1) = 2
...
f(2,6) = f(1,5) + f(1,4) + f(1,3) + f(1,2) + f(1,1)
f(2,7) = f(1,6) + f(1,5) + f(1,4) + f(1,3) + f(1,2) + f(1,1) = 6
f(2,8) = f(1,6) + f(1,5) + f(1,4) + f(1,3) + f(1,2) = 5
...
此時 f(2,2) 、f(2,3) ... f(2,6)就滿足特殊情況一,而 f(2,8) 、f(2,9) ... f(2,12)就滿足特殊情況二;
遞歸處理會超時,這里使用數組保存每n個骰子的Sum和值可能性,再生成n+1中骰子的和值可能性分布;
代碼偷了個懶,和值分布是對稱的,這里只生產一半數據,后面數據復制過去即可。
數組result[i],因為第 i 個元素代表 i+1個骰子,所以長度為 5*(i+1) +1,
頂峰值為第3n個元素,由於 i 為奇數時,數組長度為偶數,頂峰值有兩個,3n和3n+1,同樣是對稱的。
貼一下和值可能性分布數組:
n=1 : [1, 1, 1, 1, 1, 1]
n=2 : [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
n=3 : [1, 3, 6, 10, 15, 21, 25, 27, 27, 25, 21, 15, 10, 6, 3, 1]
n=4 : [1, 4, 10, 20, 35, 56, 80, 104, 125, 140, 146, 140, 125, 104, 80, 56, 35, 20, 10, 4, 1]
n=5 : [1, 5, 15, 35, 70, 126, 205, 305, 420, 540, 651, 735, 780, 780, 735, 651, 540, 420, 305, 205, 126, 70, 35, 15, 5, 1]
n=6 : [1, 6, 21, 56, 126, 252, 456, 756, 1161, 1666, 2247, 2856, 3431, 3906, 4221, 4332, 4221, 3906, 3431, 2856, 2247, 1666, 1161, 756, 456, 252, 126, 56, 21, 6, 1]
n=7 : [1, 7, 28, 84, 210, 462, 917, 1667, 2807, 4417, 6538, 9142, 12117, 15267, 18327, 20993, 22967, 24017, 24017, 22967, 20993, 18327, 15267, 12117, 9142, 6538, 4417, 2807, 1667, 917, 462, 210, 84, 28, 7, 1]
n=8 : [1, 8, 36, 120, 330, 792, 1708, 3368, 6147, 10480, 16808, 25488, 36688, 50288, 65808, 82384, 98813, 113688, 125588, 133288, 135954, 133288, 125588, 113688, 98813, 82384, 65808, 50288, 36688, 25488, 16808, 10480, 6147, 3368, 1708, 792, 330, 120, 36, 8, 1]
n=9 : [1, 9, 45, 165, 495, 1287, 2994, 6354, 12465, 22825, 39303, 63999, 98979, 145899, 205560, 277464, 359469, 447669, 536569, 619569, 689715, 740619, 767394, 767394, 740619, 689715, 619569, 536569, 447669, 359469, 277464, 205560, 145899, 98979, 63999, 39303, 22825, 12465, 6354, 2994, 1287, 495, 165, 45, 9, 1]
n=10 : [1, 10, 55, 220, 715, 2002, 4995, 11340, 23760, 46420, 85228, 147940, 243925, 383470, 576565, 831204, 1151370, 1535040, 1972630, 2446300, 2930455, 3393610, 3801535, 4121260, 4325310, 4395456, 4325310, 4121260, 3801535,3393610, 2930455, 2446300, 1972630, 1535040, 1151370, 831204, 576565, 383470, 243925, 147940, 85228, 46420, 23760, 11340, 4995, 2002, 715, 220, 55, 10, 1]
源碼:
class Solution: # @param {int} n an integer # @return {tuple[]} a list of tuple(sum, probability) def dicesSum(self, n): # Write your code here if n == 0 : return None result = [ [1,1,1,1,1,1], ] # if n == 1: return result[0] # 計算n個骰子出現的各個次數和 for i in range(1,n): x = 5*(i+1)+1 result.append([0 for _ in range(x)]) for j in range(x): if j < 6: result[i][j] = (sum(result[i-1][0:j+1])) elif 6 <= j <= 3*i+2: result[i][j] = (sum(result[i-1][j-5:j+1])) else: break left = 0 right = len(result[i]) - 1 while left <= right: result[i][right] = result[i][left] left += 1 right -= 1 res = result[-1] all = float(sum(res)) other = [] # 第i個元素代表骰子總和為n+i for i,item in enumerate(res): # pro = self.round(item/all) # 自己寫的四舍五入算法和LintCode有出入,其實網站自身會處理數據,這里不再做處理 pro = item/all other.append([n+i,pro]) return other def round(self,num): # 將概率值四舍五入 num = num*100 num = int(2*num)/2+int(2*num)%2 num = num/100.0 return num