[Offer] [60] [] of n dice

Title Description

  The n dice thrown on the ground, all the dice up one side and the number of points for the S. Enter n, print out the probabilities of all possible values ​​of s occurring.
  

[Cow brush off questions address network] No

Ideas analysis

  1. Recursive method. To determine the n and dice, the dice may be divided into n number of first piles: the first stack is only one; another pile has the n-1. It is possible to separate a number of points 1 to 6 appear. We need to calculate the number of points and each of the remaining n-1 dice 1 to 6 points and calculated. Next, the remaining n-1 are still dice into two piles: the first stack is only one; second stack has n-2 th. We put that on a separate dice and dice this round alone sum, and then the remaining n-2 dice to calculate the points and. Analysis here, we find that this is a recursive thinking, recursive end condition is that last only a dice. We can define an array of length 6n n + 1 and save the number of points and the number of occurrences of s to elements of the array in the sn.
  2. You can change an idea to solve this problem. We can consider two times each array to store the total number of dice appear. In one cycle, the first array of n digital n represents the number of dice and to appear . The next pass of the loop, we add a new die, and at this time the number of occurrences of n dice should be equal to one cycle of dice and n-1, n-2, n-3, n-4 the sum of the number n-5 and n-6, so we put an array of n-1 before the n-th digit corresponding to another array, n-2, n-3 , n-4, n- 5 and n-6 digital sum.

Test Case

  1. Functional test: 1,2,3,4 probability of each point of the dice.
  2. Special input test: Enter 0.
  3. Performance Test: entering a large number such as 11.

Java code

public class Offer060 {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
        
        

    }

    private static final int maxValue = 6;

    public static void printProbability1(int number) {
        Solution1(number);
    }

    /**
     * 方法一:递归解法
     */
    private static void Solution1(int number) {
        if (number <= 0)
            return; // 错误
        int[] probabilities = new int[maxValue * number - number + 1];
        // 下标为i,对应的值代表点数之和为i+number总共出现的情况次数
        // 点数从number~maxValue*number,所以数组大小为6*number-number+1
        for (int i = 0; i < probabilities.length; i++)
            probabilities[i] = 0;

        // 计算不同点数出现的次数
        for (int i = 1; i <= maxValue; i++)
            calP(probabilities, number, number - 1, i); // 第一次掷骰子,总点数只能是1~maxValue(即6)

        int totalP = (int) Math.pow(maxValue, number); // 所有情况总共出现的次数
        for (int i = 0; i < probabilities.length; i++) {
            double ratio = (double) probabilities[i] / totalP;
            NumberFormat format = NumberFormat.getPercentInstance();
            format.setMaximumFractionDigits(2);// 设置保留几位小数
            System.out.println("点数和为" + (i + number) + "的概率为:" + format.format(ratio));
        }
    }

    /**
     * 计算每种点数出现的次数
     * 
     * @param number:骰子总个数
     * @param curNumber:当前剩余骰子个数
     * @param sum:各个骰子加起来的总点数
     */
    private static void calP(int[] probabilities, int number, int curNumber, int sum) {
        if (curNumber == 0) {
            probabilities[sum - number]++; // 总数为sum的情况存放在sum-number下标中
            return;
        }
        for (int i = 1; i <= maxValue; i++)
            calP(probabilities, number, curNumber - 1, sum + i); // 相当于剩余的骰子少一个,总点数增加。
    }

/**
     * 方法二
     * @param number
     */
    private static void Solution2(int number) {
        if (number <= 0)
            return; // 错误
        int[][] probabilities = new int[2][number * maxValue + 1];
        // [2]代表用两个数组交替保存,[number*maxValue+1]是指点数为所在下标时,该点数出现的总次数。
        // probabilities[*][0]是没用的,只是为了让下标对应点数
//      for (int i = 0; i < 2; i++) {
//          for (int j = 0; j < number * maxValue; j++) {
//              probabilities[i][j] = 0;
//          }
//      }

        for (int i = 1; i <= 6; i++)
            probabilities[0][i] = 1; // 第一个骰子出现的情况

        int flag = 0;
        for (int curNumber = 2; curNumber <= number; curNumber++) { // 当前是第几个骰子
            for (int i = 0; i < curNumber; i++)
                probabilities[1 - flag][i] = 0; // 前面的数据清零

            for (int i = curNumber; i <= curNumber * maxValue; i++) {
                for (int j = 1; j <= 6 && j <= i; j++) {
                    probabilities[1 - flag][i] += probabilities[flag][i - j];
                }
            }
            flag = 1 - flag;

        }

        int totalP = (int) Math.pow(maxValue, number); // 所有情况总共出现的次数
        for (int i = number; i <= number * 6; i++) {
            double ratio = (double) probabilities[flag][i] / totalP;
            NumberFormat format = NumberFormat.getPercentInstance();
            format.setMaximumFractionDigits(8);// 设置保留几位小数
            System.out.println("点数和为" + (i + number) + "的概率为:" + format.format(ratio));
        }
    }

    private static void test1() {

    }

    private static void test2() {

    }

    private static void test3() {

    }

}

Code link

Offer to prove safety codes -Java

Guess you like

Origin www.cnblogs.com/haoworld/p/offer60-n-ge-tou-zi-de-dian-shu.html