加载的骰子的数据结构?


130

假设我有一个n面加载的模具,其中每边k 滚动时都有几率p k上升。我很好奇是否有一个好的算法可以静态地存储此信息(即固定的概率集),以便我可以有效地模拟骰子的随机滚动。

目前,我有一个O(lg n)解决方案。这个想法是存储所有k的前k个边的累积概率表,它们生成[0,1)范围内的随机实数,并对该表执行二进制搜索以获取其累加最大索引。值不大于所选值。我更喜欢这种解决方案,但是运行时没有考虑到这些可能性似乎很奇怪。特别是,在极端情况下,一侧总是出现或值均匀分布,尽管我的解决方案仍将采用对数步的许多方法,但可以通过朴素的方法在O(1)中生成滚动结果。

有人对运行时以某种“自适应”方式解决此问题有任何建议吗?

编辑:基于对这个问题的回答,我写了一篇文章,描述了解决这个问题的许多方法以及它们的分析。看起来Vose对别名方法的实现为每个模具辊提供了Θ(n)预处理时间和O(1)时间,这确实令人印象深刻。希望这是对答案中包含的信息的有用补充!


2
每个特定案例都有一个O(1)解决方案是合理的。
蒂姆(Tim)

Answers:


117

您正在寻找一种别名方法,该方法提供一种O(1)方法,用于生成固定的离散概率分布(假设您可以在固定时间内访问长度为n的数组中的条目),并设置一次O(n) 。您可以在Luc Devroye撰写的“非均匀随机变量生成”第3章(PDF)中找到该文档。

这个想法是采用概率数组p k并产生三个新的n元素数组q k,a k和b k。每个q k是介于0和1之间的概率,每个a k和b k是介于1和n之间的整数。

我们通过在0和1之间生成两个随机数r和s来生成1和n之间的随机数。令i = floor(r * N)+1。如果q i <s,则返回a i,否则返回b i。别名方法的工作是弄清楚如何产生q k,a k和b k


对于这种有用的算法,别名方法并不十分出名。
mhum 2011年

作为记录:我使用别名方法apps.jcns.fz-juelich.de/ransampl发布了一个用于随机采样的C语言库。
约阿希姆W

1
别名方法的具体实现方式可以是然后较慢与较差的时间复杂度的方法如轮盘赌 对于给定的n和随机数的选定数量的,以产生由于参与执行算法常数因子。
jfs

4

使用平衡的二进制搜索树(或数组中的二进制搜索)并获得O(log n)复杂度。每个骰子结果只有一个节点,并且键是触发该结果的间隔。

function get_result(node, seed):
    if seed < node.interval.start:
        return get_result(node.left_child, seed)
    else if seed < node.interval.end:
        // start <= seed < end
        return node.result
    else:
        return get_result(node.right_child, seed)

该解决方案的优点是实现起来非常简单,但仍然具有很好的复杂性。


像上面这样的手工二叉树很容易实现,但不能保证达到平衡
yusong

如果以正确的顺序构造它,则可以保证它是平衡的。
hugomg

3

我正在考虑对您的桌子进行细化处理。

您可以创建一个长度为xN的整数数组,而不是使用每个模具值的累加表,其中x最好是一个大数,以提高概率的准确性。

使用索引(由xN归一化)作为累积值填充此数组,并在该数组中的每个“插槽”中存储该索引出现时将要掷出的骰子。

也许我可以用一个例子来解释一下:

使用三个骰子:P(1)= 0.2,P(2)= 0.5,P(3)= 0.3

创建一个数组,在这种情况下,我将选择一个简单的长度,例如10。(即x = 3.33333)

arr[0] = 1,
arr[1] = 1,
arr[2] = 2,
arr[3] = 2,
arr[4] = 2,
arr[5] = 2,
arr[6] = 2,
arr[7] = 3,
arr[8] = 3,
arr[9] = 3

然后要获得概率,只需将0到10之间的数字随机化,然后简单地访问该索引即可。

此方法可能会降低精度,但是增加x并满足精度要求。


1
为了获得完全的准确性,您可以首先进行数组查找,对于与多个面相对应的数组间隔,请在其中进行搜索。
aaz 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.