计划和平的党

时间:2014-09-09 12:50:26

标签: algorithm permutation

有一些人互相讨厌,有些人彼此相爱,有些人彼此不认识......如果(A讨厌B和A坐在B旁边)或(A爱B和A不坐在旁边B)这将是一场战争。我正在准备我朋友的生日聚会,所以我不想让聚会变成战场,我有一个这样的清单:

a1讨厌a2

a1喜欢a3

a3喜欢a2

...

是否有一个有效的算法来安排我朋友的朋友座位,这样我们就不会有战争?

我目前正在使用nave强力解决方案,生成所有排列以找到可行的安排。

2 个答案:

答案 0 :(得分:3)

您应将此视为图形问题。我以为你想把客人围成一圈。

V成为您的客人。让E成为所有顶点对(A, B)的集合,这样AB就不会互相讨厌。在此图中找到哈密顿循环已经解决了彼此讨厌的人不能坐在一起的问题,因为那些边缘不存在。

现在你需要强迫彼此相爱的人坐在一起。对于每对顶点(A, B)AB彼此相爱,请添加顶点A'B',边(A, A'),{{ 1}}和(B, B')(A', B')A'都有度B',因此您的汉密尔顿周期必须包含2

现在,只需找到哈密尔顿循环,你就有了座位布局。不幸的是,这个问题是NP完整的,但至少它是经过深入研究的。

答案 1 :(得分:1)

如果你关心的不仅仅是相邻的定位(例如,如果人们不能彼此坐在一起),那么我个人会使用genetic algorithm

你知道什么是合格的比赛,但很难到达那里。

PSEUDO CODE ALERT

我们假设你有一个人的数据模型

person
  +loves : person[]
  +hates : person[]
  +id : string //typically name, or a b c in your example

你有一个计算两个人适合度的功能

okToSitNextToEachOther(person1 : person, person2 : person) 
   return (person1.loves.contains(person1) ? 1 : 0) + 
          (person1.hates.contains(person2) ? -2 : 0); // hate more important than love
          //do the same for person2 if hate/love is directional

创建表格排列的数据模型。然后创建一个评估排列拟合的函数。

table
  -x : int //length of a table side, set in constructor
  +seatRow1 : person[x]
  +seatRow2 : person[x]
  +calculateMatch() : float //you could return int of error count or a percentage
  +mutate() : void // randomly swap people who violates your rule around

创建一个随机填充x表的管理器(为您的人口提供足够的表)。 让经理能够改变最少匹配的表的数据。 (变异意味着交换周围的人)。

PartyManager
  -people : person[] //pass in constructor
  -tables : table[]
  +calculateMatch() : float //iterate over all tables and return sum of match
  +mutate() : void //iterate over all tables and mutate those who does not suit match requirement
  +clone() : PartyManager //clone this 

现在创建许多经理并将它们全部放在列表中。 循环,直到其中一位经理有足够好的'安排。直到那时。每个经理都要调用mutate。删除最不成功的,并为每个删除创建一个新的,并使用最成功的种子,然后对那些运行mutate。

PartyManager match = null
while (true) {
   PartyManager bestManager = managers.max( m => m.calculateMatch() ) //find the best match
   for each partyManager in managers
       if partyManager.calculateMatch() < TOO_BAD
           clone = bestManager.clone()
           clone.mutate()
           managers.add(clone)
           managers.remove(partyManager)
       else if partyManager.calculateMatch() < GOOD_ENOUGH
           partyManager.mutate()
       else
           match = partyManager // we fount a match
           break

如果您需要我,我可以填写更多信息,但请查看我链接到的维基。