劍指Offer對答如流系列 n個骰子的點數

2021-10-02 11:29:37 字數 2198 閱讀 3101

把n個骰子扔在地上,所有骰子朝上一面的點數之和為s。輸入n,列印出s的所有可能的值出現的概率。

這個問題需要點高中數學的知識。

對於n個骰子,要計算出每種點數和的概率,我們知道投擲n個骰子的總情況一共有6^n種,因此只需要計算出某點數和的情況一共有幾種,即可求出該點數之和的概率。

思路一:遞迴暴力

我們知道點數之和s的最小值為n,最大值為6*n,因此考慮用乙個大小為(6*n-n+1)的陣列存放不同點數之和的情況個數,那麼,如果點數之和為x,那麼把它出現的情況總次數放入陣列種下標為x-n的元素裡。

確定了如何存放不同點數之和的次數之後,我們要計算出這些次數。我們把n個骰子分為1個骰子和n-1個骰子,這1個骰子可能出現1~6個點數,由該骰子的點數與後面n-1個骰子的點數可以計算出總點數;而後面的n-1個骰子又可以分為1個和n-2個,把上次的點數,與現在這個骰子的點數相加,再和剩下的n-2個骰子的點數相加可以得到總點數……,即可以用遞迴實現。在獲得最後乙個骰子的點數後可以計算出幾個骰子的總點數,令陣列中該總點數的情況次數+1,即可結束遍歷。

可以感受到,計算量實在太大了,效率會比較低。

思路二:動態規劃

劍指offer的解答過於繁瑣與複雜。這裡提供一種相對理解簡單,容易實現的方法。

我們通過分析能夠發現 n個骰子的點數依賴於n-1個骰子的點數,相當於在n-1個骰子點數的基礎上再進行投擲。

由此定義狀態轉移方程為f(n,k)表示n個骰子點數和為k時出現的次數,於是可得:

f(n,k)=f(n−1,k−1)+f(n−1,k−2)+f(n−1,k−3)+f(n−1,k−4)+f(n−1,k−5)+f(n−1,k−6)

其中 n>0且k<=6n,f(n−1,k−i)表示的是第n次擲骰子時,骰子的點數為i對應的情況

從k−1到k−6分別對應第n次擲骰子時骰子正面為1到6的情況。而初始狀態可以定義為:

f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1

思路一:

private

final

int maxvalue =6;

public

void

printprobability1

(int number)

int[

] probabilities =

newint

[maxvalue*number-number+1]

; arrays.

fill

(probabilities,0)

;//計算不同點數出現的次數

for(

int i=

1;i<=maxvalue;i++

)//所有情況總共出現的次數

int totalp =

(int

) math.

pow(maxvalue, number)

;for

(int i=

0; iprivate

void

calp

(int

probabilities,

int number,

int curnumber,

int sum)

for(

int i=

1; i<=maxvalue; i++

)}

思路二:

public

void

printprobability

(int number)

}private

intgetnsumcount

(int n,

int sum)

if(n==1)

int rescount;

rescount =

getnsumcount

(n-1

,sum-1)

+getnsumcount

(n-1

,sum-2)

+getnsumcount

(n-1

,sum-3)

+getnsumcount

(n-1

,sum-4)

+getnsumcount

(n-1

,sum-5)

+getnsumcount

(n-1

,sum-6)

;return rescount;

}

劍指Offer對答如流系列 求1 2 n

求1 2 n,要求不能使用乘除法 for while if else switch case等關鍵字及條件判斷語句 a?b c 有了那麼多限制,剩下的我們可以選擇 既然是乙個等差數列,和為 n 1 n 2 我們之前詳細 了位運算劍指offer對答如流系列 二進位制中 1 的個數,不需要 就能夠實現加...

劍指Offer對答如流系列 醜數

我們把只包含質因子2 3和5的數稱作醜數 ugly number 求按從小到大的順序的第n個醜數。例如6 8都是醜數,但14不是,因為它包含質因子7。習慣上我們把1當做是第乙個醜數。判斷乙個數是不是醜數,最容易想到的方法就是讓這個數不斷除以2,3,5。對於第n個醜數,只要從1開始,依次判斷每個數是不...

劍指Offer對答如流系列 剪繩子

給你一根長度為n繩子,請把繩子剪成m段 m n都是整數,n 1並且m 1 每段的繩子的長度記為k 0 k 1 k m k 0 k 1 k m 可能的最大乘積是多少?例如當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此時得到最大的乘積18。遇到問題,先分析問題,由分析的結果確定所運用的演...