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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值