首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用N个六边骰子计算得到和X的概率

如何用N个六边骰子计算得到和X的概率
EN

Stack Overflow用户
提问于 2020-03-04 15:31:08
回答 2查看 1K关注 0票数 3

的挑战:例如,,当使用3个六边骰子时,得到15之和的概率是多少?例如,可以获得5-5-5或6-6-3或3-6-6或更多的选项。

-2骰子的蛮力解-复杂度为6^2:

假设我们只有两个六边骰子,我们可以编写这样一个非常基本的代码:

代码语言:javascript
复制
public static void main(String[] args) {
   System.out.println(whatAreTheOdds(7));
}

public static double whatAreTheOdds(int wantedSum){
    if (wantedSum < 2 || wantedSum > 12){
        return 0;
    }

    int wantedFound = 0;
    int totalOptions = 36;

    for (int i = 1; i <= 6; i++) {
        for (int j = 1; j <= 6; j++) {
            int sum = i+j;
            if (sum == wantedSum){
                System.out.println("match: " + i  + " " + j );
                wantedFound +=1;
            }
        }
    }

    System.out.println("combinations count:" + wantedFound);
    return (double)wantedFound / totalOptions;
}

7的输出将是:

比赛:1 6 比赛:2 5 比赛:3 4 比赛:4 3 比赛:5 2 比赛:6 1 组合计数:6 0.16666666666666666

问题是如何推广该算法以支持N个骰子:

代码语言:javascript
复制
public static double whatAreTheOdds(int wantedSum, int numberOfDices)

因为我们不能动态地创建嵌套的for循环,所以我们必须提供一种不同的方法。

我想到了这样的事情:

代码语言:javascript
复制
 public static double whatAreTheOdds(int sum, int numberOfDices){

    int sum;
    for (int i = 0; i < numberOfDices; i++) {
        for (int j = 1; j <= 6; j++) {

        }
    }
}

但没能找到正确的算法。

这里的另一个挑战是--是否有一种有效的方法,而不是6^N的复杂性?

EN

回答 2

Stack Overflow用户

发布于 2020-03-04 17:15:13

这里是一个递归的解决方案与回忆录,以计数组合。

代码语言:javascript
复制
import java.util.Arrays;
import java.lang.Math;

class Dices {
    public static final int DICE_FACES = 6;

    public static void main(String[] args) {
        System.out.println(whatAreTheOdds(40, 10));
    }

    public static double whatAreTheOdds(int sum, int dices) {
        if (dices < 1 || sum < dices || sum > DICE_FACES * dices) return 0;

        long[][] mem = new long[dices][sum];
        for (long[] mi : mem) {
            Arrays.fill(mi, 0L);
        }
        long n = whatAreTheOddsRec(sum, dices, mem);
        return n / Math.pow(DICE_FACES, dices);
    }

    private static long whatAreTheOddsRec(int sum, int dices, long[][] mem) {
        if (dices <= 1) {
            return 1;
        }
        long n = 0;
        int dicesRem = dices - 1;
        int minFace = Math.max(sum - DICE_FACES * dicesRem, 1);
        int maxFace = Math.min(sum - dicesRem, DICE_FACES);
        for (int i = minFace; i <= maxFace; i++) {
            int sumRem = sum - i;
            long ni = mem[dicesRem][sumRem];
            if (ni <= 0) {
                ni = whatAreTheOddsRec(sumRem, dicesRem, mem);
                mem[dicesRem][sumRem] = ni;
            }
            n += ni;
        }
        return n;
    }
}

输出:

代码语言:javascript
复制
0.048464367913724195

编辑:为了记录,这个算法的复杂性仍然是O(6^n),这个答案只是为了给出一个比最简单的实现更好的一般情况下的可能实现,使用回忆录和搜索空间剪枝(只探索可行的解决方案)。

票数 1
EN

Stack Overflow用户

发布于 2020-03-04 15:51:47

这样做的目的是让一个数组存储每个骰子的当前“状态”,开始时每个骰子都在一个骰子上,然后向上数。例如,使用三个骰子,您将生成以下组合:

代码语言:javascript
复制
111
112
...
116
121
122
...
126
...
665
666

一旦你有了状态,你就可以很容易地找到你想要的和。

我把细节留给你们,因为这似乎是一个有用的学习练习:)

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60529498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档