題目: 把n個骰子扔在地上,記所有骰子朝上一面的點數和為s。輸入n,求所有可能出現的s的概率
題目分析:
常規的骰子各個面的點數分別為1,2,3,4,5,6。因此比較直觀的一種解法是,每次模擬一次骰子可能出現的各個情況,然後遞迴遍歷剩下n-1個骰子的情況,**實現如下
/** 使用遞迴的方式實現
* 也即模擬每乙個骰子的點數,當模擬到最後乙個的時候,即為所得和
* */
public static void
posibility******(int n)
//進行遞迴處理
doposibility******(sums,
0,n);
doubleposibilities = new double[maxvalue
*n+1];
double totoalsum = math.pow((double) maxvalue
,(double) n);
for(int i=0
;i*n+1
;i++)
system.out
.println(arrays.tostring(posibilities));
}private static void
doposibility******(intsums,int cursum,int n)
else
}}
由於使用的是遞迴的演算法,因此當n為10左右,速度就不太行了,根本原因還是進行了一些重複的計算
因此,繼續想辦法減少重複計算,減少重複計算的思路,當然是要從快取計算結果出發
再繼續分析投n個骰子的情況
當投第乙個骰子時,可能出現的結果為1-6
當投第二個骰子時,可能出現的結果為為2-12,
其中2出現的次數等於第乙個骰子出現1的次數(第二個骰子只能是1)
其中3出現的次數等於第乙個骰子出現2的次數加上第乙個骰子出現1的次數(第二個骰子可能是1,可能是2)
其中12出現的次數等於第乙個骰子出現6的次數(第二個骰子只能是6)
因此可以得出如下等式
f[i][n]=f[i-1][n-1]+f[i-1][n-2]+...+f[i-1][n-6]
因此,從第乙個骰子開始,儲存每乙個骰子的計算結果
再接著分析,由於計算第n個骰子的時候,只需要用到第n-1個骰子的結果
因此儲存結果的範圍可以縮小到兩個骰子,因此可以用兩個陣列來快取結果
實現**如下
/** 使用快速的方法計算
* 思路是當骰子個數為k時,和為s的情況為
* 前k-1個骰子和為s-1(第k個為1),和為s-2(第k個為2)...的總數相加
* 因此可以定義兩個陣列,用於交叉計算
* 模擬從第乙個到第n個骰子的情況
* */
public static void
posibilityfast(int n)
//用於標識當前使用哪個陣列
int flag = 0
;for(int i=1
;i<=maxvalue
;i++)
flag=(flag+1)&1
;//對每乙個骰子進行模擬
for(int i=2
;i<=n;i++)
//依次處理第i個開始到maxvalue*i
for(int j=i;j<=maxvalue
*i;j++)
}flag = (flag+1)&1;}
flag = (flag+1)&1
;doubleposibilities = new double[maxvalue
*n+1];
double totoalsum = math.pow((double) maxvalue
,(double) n);
for(int i=0
;i*n+1
;i++)
system.out
.println(arrays.tostring(posibilities));
}
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...