題目:把
n個骰子扔在地上,所有骰子朝上一面的點數之和為
s。輸入
n,列印出
s的所有可能的值出現的概率。
分析:玩過麻將的都知道,骰子一共
6個面,每個面上都有乙個點數,對應的數字是1到
6之間的乙個數字。所以,
n個骰子的點數和的最小值為
n,最大值為
6n。因此,乙個直觀的思路就是定義乙個長度為
6n-n
的陣列,和為
s的點數出現的次數儲存到陣列第
s-n個元素裡。另外,我們還知道
n個骰子的所有點數的排列數6
^n。一旦我們統計出每一點數出現的次數之後,因此只要把每一點數出現的次數除以6
^n,就得到了對應的概率。
該思路的關鍵就是統計每一點數出現的次數。要求出
n個骰子的點數和,我們可以先把
n個骰子分為兩堆:第一堆只有乙個,另乙個有
n-1個。單獨的那乙個有可能出現從1到
6的點數。我們需要計算從1到
6的每一種點數和剩下的
n-1個骰子來計算點數和。接下來把剩下的
n-1個骰子還是分成兩堆,第一堆只有乙個,第二堆有
n-2個。我們把上一輪那個單獨骰子的點數和這一輪單獨骰子的點數相加,再和剩下的
n-2個骰子來計算點數和。分析到這裡,我們不難發現,這是一種遞迴的思路。遞迴結束的條件就是最後只剩下乙個骰子了。
*************************= 以上文字引用自原文(劍指offer) *************************===
思路一明晰了,**應該不難寫,同樣引用原文的**:
#define max_value 6
void printp1(int n)
{ if(n<1) return ;
int maxsum=n*max_value;
int *p=new int[maxsum-n+1];
for(int i=n;i<=maxsum;i++)
p[i-n]=0;//初始化
pro(n,p);
double total=pow((double)max_value,n);
for(int i=n;i<=maxsum;i++)
{ double ratio=(double)p[i-n]/total;
cout<
動態規劃就是分階段考慮問題,給出變數,找出相鄰階段間的關係。具體定義給忘了。
1.現在變數有:骰子個數,點數和。當有k個骰子,點數和為n時,出現次數記為f(k,n)。那與k-1個骰子階段之間的關係是怎樣的?
2.當我有k-1個骰子時,再增加乙個骰子,這個骰子的點數只可能為1、2、3、4、5或6。那k個骰子得到點數和為n的情況有:
(k-1,n-1):第k個骰子投了點數1
(k-1,n-2):第k個骰子投了點數2
(k-1,n-3):第k個骰子投了點數3
....
(k-1,n-6):第k個骰子投了點數6
在k-1個骰子的基礎上,再增加乙個骰子出現點數和為n的結果只有這6種情況!
所以:f(k,n)=f(k-1,n-1)+f(k-1,n-2)+f(k-1,n-3)+f(k-1,n-4)+f(k-1,n-5)+f(k-1,n-6)
3.有1個骰子,f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1。
**如下:
void printp(int n)
{ if(n<1) return;
int *ppro[2];
ppro[0]=new int[n*max_value+1];
ppro[1]=new int[n*max_value+1];
for(int i=0;i
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...