使用邻接规则将循环链表随机化

时间:2019-04-10 16:09:13

标签: algorithm random linked-list

假设您有一个任意大小的大圆桌,您想让所有客人随机地坐在桌旁,但有一些关于邻接的规则。

示例:爱丽丝,鲍勃,查理,丹,夏娃,弗兰克,格里和海蒂来吃饭。创建一个随机的座位安排,使爱丽丝不在格里旁边,而查理不在弗兰克旁边。

到目前为止,由于我很懒惰并且可以工作,因此我一直在通过对列表进行混排来进行此操作,然后在结果违反任何邻接限制的情况下仅进行混排。不过,我很幸运,我的“来宾列表”很大,而且我的限制很少,所以失败的情况很少。

我猜想更好解决方案涉及:

  • 使用尾部递归,以便我仅备份解决冲突所必需的内容,而不是重新整理整个列表并希望达到最佳效果。
  • 按照每个条目的排除数量对初始列表进行排序,以便首先解决“烦恼”项,而尾部还有更多选项。

尽管我正在研究它,但我发现自己想知道是否有一种方法可以预先检测某个列表的邻接排除是否无法满足。也许通过构建一棵具有“合法”选项的树并查看其深度是否小于列表的长度?

2 个答案:

答案 0 :(得分:4)

在不偏向分布的情况下向要采样的空间添加约束可能非常困难。如果您进行部分回溯,那么您将较早放置的项目优先于较晚放置的项目,从而使较早放置的项目的分布更接近(不受约束的)随机混洗所期望的分布,同时放大了约束对较晚放置的项目的影响。放置的。考虑一种情况,其中仅爱丽丝(Alice),尤兰达(Yolanda)和塞尔达(Zelda)被允许坐在贝丝旁边。如果按字母顺序分配座位,并且在遇到无法解决的情况时进行回溯,那么爱丽丝最终比贝斯更不会出现在其他两个贝斯旁边,因为贝斯一开始不太可能会被放在爱丽丝旁边,并且回溯永远不会让您搬贝丝。

您所说的“懒惰”被称为rejection sampling,通常是解决此类问题的首选方法,因此请不要短时间出售。对于您将要拒绝很多空间的情况,有几种拒绝采样的变体,一旦绕开它们,它们便可以很好地工作。使用the Metropolis-Hastings algorithm也取得了不错的效果,它更易于理解和利用(IMO)。如果您只想要一个样本,则可以进行老化阶段,然后仅获取当前状态。

答案 1 :(得分:1)

您尚未描述对您的约束的任何限制。因此,简单的答案是“否”:没有一种方法可以确定是否存在解决方案,除非通过所有允许的序列来寻找满足所有约束的方法。

如果您可以表征约束,那么您可以根据这些属性来指导搜索。 如果约束 all 具有适合形式证明的逻辑属性,那么您将拥有一个系统,在其中您将有机会获得“是/否”结果搜索约束空间,而不是N!蛮力座位搜索的空间。


可能的方法

我们想让最大的投诉人首先就座:首先解决已知问题,以免他们导致就座失败。

  1. 初始化seat_next列表为空。
  2. 选择约束中命名的随机无座人员;添加到seat_next
  3. seat_next中弹出一个人。
  4. 找到该人的有效座位;如果没有,则返回失败(回溯)。
  5. 将在该约束中命名的其他所有人添加到seat_next
  6. 如果seat_next为空,请继续执行步骤2;否则,请转到步骤3。

根据交互作用和约束类型,仍有许多调整元素要考虑。例如,您可以根据出现的约束的数量对人员进行加权;您可能希望将约束堆叠或排队,以便在转到下一个约束之前趋向于满足一个约束。