解題筆記(18) n個骰子的點數

2021-07-16 05:02:49 字數 1280 閱讀 7341

問題描述:把

n個骰子扔在地上,所有骰子朝上一面的點數之和為

s。輸入

n,列印出

s的所有可能的值出現的概率。

思路:

這是個排列問題!

這是個排列問題!

這是個排列問題!

這是一道應用動態規劃思想的題目,而動態規劃最難的就是要找最優子結構。並採取一種稱為備忘錄的方法避免重複計算。因為備忘錄方法為每個解過的子問題建立了備忘錄,以備需要時參看,避免了相同子問題的重複求解。

本題的最優子結構為:f(k, n) 表示k個骰子點數和為n的種數,

k表示骰子個數,n表示k個骰子的點數和

/       = f(k-1, n-6) + f(k-1, n-5) + f(k-1, n-4) + f(k-1, n-3) + f(k-1, n-2) + f(k-1, n-1)        對於 k > 0, k <= n <= 6*k

f(k, n) =     

\       = 0              對於 n < k or n > 6*k

當k=1時, f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1。

當k= 2時,f(2,7) = f(1,1) + f(1,2) + f(1,3) + f(1,4) + f(1,5) + f(1,6)

= 6.

注意到了吧,f(2,7)  = 6 (1+6,2+5,3+4,4+3,5+2,6+1),這是個排列問題!所以可以用動態規劃!

從上面公式可以看出,k個骰子點數和為n的種數只與k-1個骰子的和有關。這就可以用到備忘錄的方法,用一張**儲存已解決的子問題的解,然後自底向上填表。考慮到當前層的計算只與下一層有關,因此只需儲存一行。

參考**:

const int face_num = 6; //骰子的面數

//函式功能 : n個骰子的點數

//函式引數 : number為骰子數

//返回值 : 無

void printsumprobabilityofdices(int number)

} //不可能的情況,即i個骰子的和不可能小於i

for(j = i - 1;j >= 0; j--)

psum[j] = 0;

} //列印結果

for(i = 0; i <= size; i++)

cout<<"sum = "<

n個骰子的點數

把n個骰子扔在地上,所有骰子朝上的一面的點數之和為s。輸入n,列印出s的所有可能的值和出現的概率。1 基於迴圈求骰子點數 2int g maxvalue 6 骰子的點數個數 3void printprobability int number number 為骰子個數49 int pprobabili...

n個骰子的點數

題目 把n個骰子扔在地上,所有骰子朝上一面的點數之和為s。輸入n,列印出s的所有可能的值出現的概率。方法一 遞迴 思路 設n個骰子某次投擲點數和為s的出現次數是f n,s 那麼,f n,s 等於n 1個骰子投擲的點數和為s 1 s 2 s 3 s 4 s 5 s 6時的次數的總和 f n s f n...

n個骰子的點數

題目 把n個骰子扔在地上,所有骰子朝上一面的點數之和為s。輸入n,列印出s的所有可能的值出現的概率。方法一 遞迴 思路 設n個骰子某次投擲點數和為s的出現次數是f n,s 那麼,f n,s 等於n 1個骰子投擲的點數和為s 1 s 2 s 3 s 4 s 5 s 6時的次數的總和 f n s f n...