题目:把n个色子扔在地上,所有色子朝上以免的点数之和为S.输入n,打印出所有可能的值出现的概率。
分析:
方法1:基于递归求色子点数,时间效率不高先把n个色子分成两堆:第一堆只有一个,另一对有n-1个。d单独的那个有可能出现从1到6的点数。我们需要计算从1到6的每种点数和剩下的n-1个色子来计算点数和。接下来把剩下的n-1个色子还是分成两堆,1,和n-2。我们把上一轮那个单独色子的四岸数和这一轮单独筛子的点数相加,再和剩下的n-2个色子来计算点数和。这是一种递归的思想。
方法2:利用循环求色子点数,时间性能好考虑使用两个数组来存储色子点数的每个总数出现的次数。在每次循环中,每个数组中的第n个数字表示色子和为n出现的次数。在下一循环中,我们加上一个新的色子,此时和为n的色子出现的次数应该等于上一次循环中色子点数和为n-1、n-2、n-3,n-4,n-5,n-6的次数的总和,所以我们把另一个数组的第n个数字设为前一个数组对应的第n-1、n-2、n-3,n-4,n-5,n-6之和。
代码如下:
/**
* 题目:把n个色子扔在地上,所有色子朝上以免的点数之和为S.输入n,打印出所有可能的值出现的概率。
*/
package problem2;
/**
* @author Hutongling
*
* @time:2017年3月30日 下午3:05:14
*/
public class n个色子的点数 {
//方法1:基于递归求色子点数,时间效率不高
//先把n个色子分成两堆:第一堆只有一个,另一对有n-1个。d单独的那个有可能出现从1到6的点数。我们需要计算从1到6的每种点数和剩下的n-1个
//色子来计算点数和。接下来把剩下的n-1个色子还是分成两堆,1,和n-2。我们把上一轮那个单独色子的四岸数和这一轮单独筛子的点数相加,再和剩下的
//n-2个色子来计算点数和。这是一种递归的思想。
static int g_maxValue=6;
public void printProbability(int number){
if(number<1)
return ;
int maxSum=number*g_maxValue;
int[] pProbabilities=new int[maxSum-number+1];
for(int i=number;i<=maxSum;i++)
pProbabilities[i-number]=0;
Probability(number,pProbabilities);
double total=Math.pow(g_maxValue, number);
for(int i=number;i<=maxSum;i++){
//double ratio=(double)pProbabilities[i-number]/total;
System.out.println(i+ ": " + pProbabilities[i-number] + "/" + total);
}
}
public void Probability(int number, int[] pProbabilities) {
for(int i=1;i<=g_maxValue;i++)
Probability(number,number,i,pProbabilities);
}
public void Probability(int original, int current, int sum, int[] pProbabilities) {
if(current==1)
pProbabilities[sum-original]++;
else{
for(int i=1;i<=g_maxValue;i++)
Probability(original, current-1, sum+i, pProbabilities);
}
}
//另外一种方法:利用循环求色子点数,时间性能好
//考虑使用两个数组来存储色子点数的每个总数出现的次数。在每次循环中,每个数组中的
//第n个数字表示色子和为n出现的次数。在下一循环中,我们加上一个新的色子,此时和为n的
//色子出现的次数应该等于上一次循环中色子点数和为n-1、n-2、n-3,n-4,n-5,n-6的次数的总和,
//所以我们把另一个数组的第n个数字设为前一个数组对应的第n-1、n-2、n-3,n-4,n-5,n-6之和。
public void printProbability1(int number){
if(number<1)
return ;
int[] pProbabilities[]={new int[g_maxValue*number+1],new int[g_maxValue*number+1]};
for(int i=0;i<g_maxValue*number+1;i++){
pProbabilities[0][i]=0;
pProbabilities[1][i]=0;
}
int flag=0;
for(int i=1;i<=g_maxValue;i++)
pProbabilities[flag][i]=1;
for(int k=2;k<=number;++k)
{
for(int i=0;i<k;i++)
pProbabilities[1-flag][i]=0;
for(int i=k;i<=g_maxValue * k;i++){
pProbabilities[1-flag][i]=0;
for(int j=1;j<=i&&j<=g_maxValue;j++)
pProbabilities[1-flag][i]+=pProbabilities[flag][i-j];
}
flag=1-flag;
}
double total=Math.pow((double)g_maxValue, number);
for(int i=number;i<=g_maxValue*number;i++){
//double ratio=(double)pProbabilities[i-number]/total;
System.out.println(i+ ": " + pProbabilities[flag][i] + "/" + total);
}
}
public static void main(String[] args) {
n个色子的点数 test = new n个色子的点数();
test.printProbability(5);
System.out.println();
test.printProbability1(5);
}
}
代码结果:
5: 1/7776.0
6: 5/7776.0
7: 15/7776.0
8: 35/7776.0
9: 70/7776.0
10: 126/7776.0
11: 205/7776.0
12: 305/7776.0
13: 420/7776.0
14: 540/7776.0
15: 651/7776.0
16: 735/7776.0
17: 780/7776.0
18: 780/7776.0
19: 735/7776.0
20: 651/7776.0
21: 540/7776.0
22: 420/7776.0
23: 305/7776.0
24: 205/7776.0
25: 126/7776.0
26: 70/7776.0
27: 35/7776.0
28: 15/7776.0
29: 5/7776.0
30: 1/7776.0
5: 1/7776.0
6: 5/7776.0
7: 15/7776.0
8: 35/7776.0
9: 70/7776.0
10: 126/7776.0
11: 205/7776.0
12: 305/7776.0
13: 420/7776.0
14: 540/7776.0
15: 651/7776.0
16: 735/7776.0
17: 780/7776.0
18: 780/7776.0
19: 735/7776.0
20: 651/7776.0
21: 540/7776.0
22: 420/7776.0
23: 305/7776.0
24: 205/7776.0
25: 126/7776.0
26: 70/7776.0
27: 35/7776.0
28: 15/7776.0
29: 5/7776.0
30: 1/7776.0