剑指offer——n个骰子的点数

题目描述:

把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能出现的值出现的概率。

解题思路:

  • 将n个骰子分为两堆,第一堆只有一个,剩下一堆有n-1个
  • 然后再计算n-1个骰子的点数之和,过程和第一步一致
  • 这显然是一种递归的解法
  • 总共n个骰子,有6~n种排列组合,骰子点数之和在n到6n之间,所以可以用一个5n+1的数组来存放出现点数之和的次数,将和为s的点数存放在数组的第s-n个元素里
  • 考虑到递归解法,进行了很多重复的计算,所以可以考虑使用基于循环的方法

public static int max = 6;
public static List<Map.Entry<Integer,Double>> printProbability(int number){
    List<Map.Entry<Integer, Double>> ret = new ArrayList<Map.Entry<Integer,Double>>();
    if(number<1)
        return ret;
    int maxSum = max*number;
    int[] a = new int[maxSum-number+1];
    for(int i=number;i<=maxSum;i++)
        a[i-number] = 0;
    proba(number,a);
    double total = Math.pow(max, number);
    for(int i = number;i<=maxSum;i++){
        double ratio = a[i-number]/total;
        ret.add(new AbstractMap.SimpleEntry<>(i,ratio));
    }
    return ret;
}
public static void proba(int number,int[] a){
    for(int i = 1;i<=max;i++)
        proba_ini(number,number,i,a);
}
public static void proba_ini(int original,int current,int sum,int[] a){
    if(current==1)
        a[sum-original]++;
    else {
        for(int i =1;i<=max;i++)
            proba_ini(original, current-1, sum+i, a);
    }
}
后面考虑使用动态规划的解法

猜你喜欢

转载自blog.csdn.net/caisongcheng_good/article/details/80726154