n个骰子的点数
思路:
一个骰子有6个面,点数分别是1,2,3,4,5,6,那么n个骰子的最小点数和为n,最大点数和为6n;
1、当只有一枚骰子时,它只有6种结果,即和为1,2,3,4,5,6这6种,抛一次骰子时每种结果都只可能会出现1次;
2、当有n枚骰子时,抛一次时的最小点数和为n,最大点数和为6n,其他的点数和在这之间,当求点数和为k(n<k<6n)的出现次数,那f(k) = f(k-1)+f(k-2)+f(k-3)+f(k-4)+f(k-5)+f(k-6);
那么我们用数组下标(最小点数和为n,下标从n计算开始,比n小的不赋值)代表点数和,数组对应的值代表该点数和出现的次数,数组的大小应该是: 骰子最大点数×骰子数+1;
我们用两个数组,其中一个用来存放上一轮骰子各个点数和对应的次数,另一个用来存放当新加入一个骰子的时候各个点数和对应的次数。
代码如下:
/**
* @ClassName TestDemo60
* @Description 面60
* @Author lzq
* @Date 2019/1/28 9:45
* @Version 1.0
**/
public class TestDemo60 {
// 骰子最大点数
int maxValue = 6;
public TestDemo60(int maxValue) {
this.maxValue = maxValue;
}
/**
* 计算number骰子各个点数和出现的概率
* @param number
*/
public void get_probability(int number) {
/**
* 用来保存所有可能出现的点数和的数组其下标从0开始到
* 最大点数和number*maxValue结束
*/
int length = number*maxValue+1;
//probability1用来保存上一次骰子的每个点数和出现次数
double[] probability1 = new double[length];
//probability2用来计算当新加入当前骰子的时候,每个点数和出现次数
double[] probability2 = new double[length];
/**
* 初始化第一个骰子的的点数和,只有一枚骰子时,各个点数和都是1
*/
for(int i = 1;i <= maxValue;i++) {
probability2[i] = 1;
}
int count = 1; //计数器,用来记录滑动窗口里面的数值是否超过maxValue
double sum = 0; //用来计算当前点数和出现的次数
Deque<Double> deque = new ArrayDeque<>(); //保存滑动窗口
/**
* 计算第二枚到第number枚骰子各个点数和出现的次数
*/
for(int k = 2;k <= number;k++) {
//将上一次的骰子各个点数和给probability1,记得用clone,否则只是改变了指针指向
probability1 = probability2.clone();
//重置probability2,将其清零,用于保存当前骰子的各个点数和
for(int i = 0;i <= (k-1)*maxValue;i++) {
probability2[i] = 0;
}
//将双端队列清空,用于保存上一次骰子的各个点数和的滑动窗口
deque.clear();
count = 1;
sum = 0;
/**
* 计算当前骰子的各个点数和出现的次数
*/
for(int j = k;j <= k*maxValue;j++) {
if(count <= maxValue) {
//如果当前计算的点数和小于maxValue,只需要累加即可
sum += probability1[j-1];
}else {
//如果当前计算的点数和大于maxValue,需要删除队列第一个元素
sum = sum-deque.getFirst()+probability1[j-1];
deque.removeFirst();
}
probability2[j] = sum;
deque.offerLast(probability1[j-1]);
count++;
}
}
double all = Math.pow(maxValue,number); //所以可能出现的次数总和
System.out.println("点数和"+"\t出现次数"+"\t概率");
for(int i = number;i < length;i++) {
System.out.print(i+"\t");
System.out.print(probability2[i]+"\t\t");
System.out.print(probability2[i]/all+"\n"); //概率
}
}
}
测试代码:
public static void main(String[] args) {
TestDemo60 testDemo60 = new TestDemo60(6);
testDemo60.get_probability(3);
}
运行结果:
点数和 出现次数 概率
3 1.0 0.004629629629629629
4 3.0 0.013888888888888888
5 6.0 0.027777777777777776
6 10.0 0.046296296296296294
7 15.0 0.06944444444444445
8 21.0 0.09722222222222222
9 25.0 0.11574074074074074
10 27.0 0.125
11 27.0 0.125
12 25.0 0.11574074074074074
13 21.0 0.09722222222222222
14 15.0 0.06944444444444445
15 10.0 0.046296296296296294
16 6.0 0.027777777777777776
17 3.0 0.013888888888888888
18 1.0 0.004629629629629629