1. 程式人生 > >LintCode Python 困難級題目 20.骰子求和 動態規劃

LintCode Python 困難級題目 20.骰子求和 動態規劃

題目描述:

扔 n 個骰子,向上面的數字之和為 S。給定 Given n,請列出所有可能的 S 值及其相應的概率。

 注意事項

You do not care about the accuracy of the result, we will help you to output results.

您在真實的面試中是否遇到過這個題?  Yes 樣例

給定 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

相關推薦

LintCode Python 困難題目 20.求和 動態規劃

題目描述: 扔 n 個骰子,向上面的數字之和為 S。給定 Given n,請列出所有可能的 S 值及其相應的概率。  注意事項 You do not care about the accuracy of the result, we will help you to output results.

lintcode 20. 求和 動態規劃

扔 n 個骰子,向上面的數字之和為 S。給定 Given n,請列出所有可能的 S 值及其相應的概率。  注意事項 You do not care about the accuracy of the result, we will help you to out

LintCode Python 入門題目 斐波納契數列

ima 算法 app mage 個數字 img ... 分享 spa 原題描述: 查找斐波納契數列中第 N 個數。 所謂的斐波納契數列是指: 前2個數是 0 和 1 。 第 i 個數是第 i-1 個數和第i-2 個數的和。 斐波納契數列的前10個數字是: 0, 1, 1

LintCode Python 簡單題目 鏈表求和

logs ons 高精度 text odin 追加 數字 nbsp accordion 原題描述: 你有兩個用鏈表代表的整數,其中每個節點包含一個數字。數字存儲按照在原來整數中相反的順序,使得第一個數字位於鏈表的開頭。寫出一個函數將兩個整數相加,用鏈表形式返回和。 您

LintCode Python 簡單題目 112.刪除鏈表中的重復元素

末尾 元素 簡單 remove def toggle strong 留下 logs 題目描述: 給定一個排序鏈表,刪除所有重復的元素每個元素只留下一個。 您在真實的面試中是否遇到過這個題? Yes 樣例 給出 1->1->2->null,

LintCode Python 簡單題目 451.兩兩交換鏈表中的節點

超時 size 上一個 ont nodes fin oot ron 單純 題目描述: 給一個鏈表,兩兩交換其中的節點,然後返回交換後的鏈表。 您在真實的面試中是否遇到過這個題? Yes 樣例 給出 1->2->3->4, 你應該返

Lintcode 20 求和

扔 n 個骰子,向上面的數字之和為 S。給定 Given n,請列出所有可能的 S 值及其相應的概率。樣例給定 n = 1,返回 [ [1, 0.17], [2, 0.17], [3, 0.17], [4, 0.17], [5, 0.17], [6, 0.17]]。思路:扔n

lintcode 求和

/* 今天被問到了一道lintcode上的題目,然而想了好久才想明白,看來在STL處折騰得太久,當初看《挑戰》時,粗淺地學的一點點動態規劃,已經忘得所剩無幾了... 這幾天開始上課了,寫a

求和 c++

#include<iostream> #include<iomanip> #define MAXLENGTH 100 using namespace std; void dict(int* result, int num, int sum) { i

NYOJ 題目79 攔截導彈(動態規劃,最長遞增序列)

攔截導彈 時間限制:3000 ms  |  記憶體限制:65535 KB 難度:3 描述 某國為了防禦敵國的導彈襲擊,發展中一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發

最長公共串與序列-動態規劃(Python)

最長公共子串(The Longest Common Substring)        LCS問題就是求兩個字串最長公共子串的問題。解法就是用一個矩陣來記錄兩個字串中所有位置的兩個字元之間的匹配情況,若是匹配則為左上方的值加1,否則為0。然後求出對角線最長的1的序列,其對應

C++求解漢字字符串的最長公共序列 動態規劃

esp style mes else if c++ char 那種 size 公共子序列 近期,我在網上看了一些動態規劃求字符串最長公共子序列的代碼。可是無一例外都是處理英文字符串,當處理漢字字符串時。常常會出現亂碼或者不對的情況。 我對代碼進行了改動。使用wc

甲級PAT 1046 Shortest Distance (20 分)(動態規劃

1046 Shortest Distance (20 分) The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed

P2679 [NOIP2015]串-動態規劃,字串

有兩個僅包含小寫英文字母的字串 AA 和 BB。 現在要從字串 A 中取出 k 個互不重疊的非空子串,然後把這 k 個子串按照其在字串 A 中出現的順序依次連線起來得到一個新的字串。請問有多少種方案

300.Longest Increasing Subsequence 最長遞增序列 動態規劃

題目 給定一個未排序的整數陣列,找到最長遞增子序列的長度。 思路 動態規劃,使用一個數組dp記錄原陣列每一個位置的數字和到這個位置為止的最長子序列長度,dp陣列元素是元組——(a:當前位置最長子序列長度,b:當前位置數字),遍歷陣列,每遍歷到一個數字i,找到

leetcode 718. Maximum Length of Repeated Subarray 最長公共串 + 動態規劃DP

Given two integer arrays A and B, return the maximum length of an subarray that appears in both arrays. Example 1: Input: A: [1,

最大連續序列——動態規劃經典問題

前幾天在牛客網上看到一道關於動態規劃的題目,完全不知如何著手。所以就去學習了一下動態規劃,參考網上的解析,跌跌撞撞把一道杭電上的最大連續子序列敲了出來。 題目來源: http://acm.hdu.edu.cn/showproblem.php?pid=1231 給定K個整數的

最長遞減序列--動態規劃

例如:有一個序列,例如 9 8 2 1 7 5 3 4 3 2 1.      求出最長的遞減子序列。如本例的結果就是:9 8 7 5 4 3 2 1。 分析:         可採用動態規劃的思想進行解答,時間複雜度為O(n^2).        設原陣列為a[1

夕拾演算法進階篇:16)最長迴文串(動態規劃DP)

給出一個字串S,求S的最長迴文子串的長度。 樣例:字串“PATZJUJZTACCBCC”的迴文子串為“ATZJUJZTA”,長度為9。 如果使用暴力解法,列舉子串的兩個端點i和j,時間複雜度需要O(n^2)。判斷子串是否為迴文需要O(n),總體時間複雜度為O(n^3),使用

POJ 1458/HDU 1159 最長公共序列 (動態規劃)

題目連結:poj && hdu 程式碼 #include <iostream> #include <cstdio> #include <algo