哪种算法可以解决我的婚礼表问题?

时间:2013-10-02 17:51:20

标签: algorithm

我有x位客人参加我的婚礼和y桌子的z座位。客人A可以和客人B坐在同一张桌子上,客人C不能和客人D坐在同一张桌子上,....

鉴于所有客人之间所有连接的数据集,是否有一种已知的算法可以解决这类问题?

我确信这种问题有一个抽象的父母被称为“问题x”或某种东西,或者它可能是问题a和问题b的组合,可以通过组合算法y和z来解决

赞赏正确方向的任何一点。

4 个答案:

答案 0 :(得分:7)

如果您需要精确的解决方案,请将其表示为0-1整数程序并使用GLPK来解决它。

如果将i分配给表j,则x_ij为1,否则为0。请考虑以下约束集:

(i)sum_ {j = 1 ... y} x_ij = 1表示i = 1 ... x

(ii)sum_ {i = 1 ... x} x_ij< = z,j = 1 ... y

(iii)对于j = 1 ... y

,x_ij + x_kj <= 1

(iv)x_ij是二进制

约束(i)确保每个人都被分配。约束(ii)防止表超载。约束(iii)是针对不能坐在一起的每个人对(i,k)定义的。

将其插入GLPK,CPLEX或GUROBI,只要问题不是太大,您就可以开展业务。正如其他人所提到的那样,NP硬度意味着事情会变得丑陋。

答案 1 :(得分:5)

这个问题在一般情况下是NP难的,所以如果表或客户数量很大,你不应该期望找到一个有效的通用解决方案。这个问题是this earlier problem的一个变体,它根据他们的喜好询问将人们分配到不同的房子,你可以通过简单地给每个表足够的容量来减少这个问题(这是NP难的)每一位客人。

如果每个桌子的人数很少而且客人数量很少,您可以通过尝试每个可能的任务来强制解决方案。另一个选择是尝试随机猜测一些解决方案,然后逐步修改它们以尝试找到有效的解决方案(例如,使用爬山算法)。

希望这有帮助!

答案 2 :(得分:1)

这是一个NP难题,所以你找不到一般的解决方案。事实上,即使找到能够坐在一张桌子上的z客人也是NP难的。

但是,如果您没有太多的访客冲突,那么启发式操作可能会起作用。例如:

Pick an unseated guest G with a maximal number of incident edges (conflicts)
  If G has a conflict with someone seated at each table, then fail
  Else assign G at random to an available table
Repeat until all guests are seated

稍微好一点的启发式方法包括跟踪每个客户的所有可能表。一开始,每位客人都可以坐在任何一张桌子上。

Pick an unseated guest G such that the size of G.availableTables is minimal
  If G.availableTables is empty, then fail
  Assign G at random to a table T from G.availableTables
  For each guest G2 who is in conflict with G
    remove T from the set G2.availableTables
Repeat until all guests are seated.

您还可以修改此启发式以使其更加强大,并为每个表格T跟踪有多少未定位的客人能够填充剩余的座位。然后,当您将一个访客分配到一个表格时,而不是随意选择,您会优先选择剩余席位较多的桌子以及能够坐在其中的人数较少。

在实践中,如果在尝试几百次随机尝试后这样的启发式方法不起作用,那么它可能是一个难以解决的问题。

答案 3 :(得分:1)

我知道这个问题是在几年前提出的,但仍然是针对那些遇到类似问题的人。

问题的定义

我的问题是类似的:考虑到某些喜好,在婚礼上让人们坐在哪里?它与最初的问题并不完全相同,但是正确设置首选项后,您可以制定最初的问题。

我没有读到那些复杂的问题及其解决方法。我只是想到了另一种方法。我敢肯定这不是解决问题的最佳方法,但它有效且易于实现。

方法

我选择了一种模型,其中一个人可以陈述其想坐在另一个人的同一个桌子上的意愿。我们称它们为重量。因此,Sara可以通过施加一个权重(例如从-5到5)来表达自己的愿望,即在迈克尔的同一张桌子上坐(5)或不坐(-5)。也许她不在乎(0),或者迈克尔很帅,但有点小(2),或者也许他很好,但闻起来很奇怪(-3)。

让w_ij为与我要与人j坐在同一张桌子上的人的欲望相关的权重。请注意,w_ij不一定等于w_ji(Sara可能喜欢Michael,但也许Michael讨厌Sara)。然后,让我们如下定义表格的评分:

rating_table = 1/N * sum_i sum_j w_ij

其中N是表中的人数。注意,权重之和是Nx(N-1)/ 2个项(包括0个项)的和。想象一下,在一张桌子上有3个人,那么有6个砝码,而不是9个(一个人不想和自己坐在同一张桌子上……)。

然后,平均评分是每个rating_table的总和除以表格数。该平均评分是我打算最大化的评分。

算法的思想如下。假设您有一个初步的解决方案(例如,人们随机坐在桌子旁)。然后,如果您将一个桌子的一个人i切换到另一个桌子的一个人j,会发生什么?两个表的等级都会改变。我们将那些潜在的变化保存在有序向量中。最后,我们将有一个结构向量,每个结构都包含当人i与人j切换时等级的变化(两个表的等级变化之和)。当您拥有所有可能的变化时,我们将对向量进行迭代,从评级的最大变化开始,然后 切换人员。具体步骤如下。

算法

1)计算结构的向量,其中包含对要切换的人员,其来自的表的引用,以及每个表在切换过程中所经历的评级差异之和。我们称其为总体评级变化。

2)遍历结构的向量:如果总体评级变化为正,则用j切换人i。假设人i来自表A,人j来自表B。由于表A和B的设置已更改,因此我们无法在这些表之间来回切换。因此,如果向量包含与那些表之一相关的另一个开关,则必须跳过它。循环结束后,我们可以重新开始。因此,每个表最多可在1个循环中进行1次切换。

3)只要额定值的变化为正,并且在转换期间尚未使用表A和B,则继续进行转换。请注意,一张桌子可能增加了2张,第二张桌子减少了1张。总体变化仍然是积极的。

4)返回步骤1。现在,我们可以在所有表​​之间再次切换。同样,我们只能在1个循环中从表A和B切换一次人员。

5)继续执行此操作,直到所有总体评分更改为负或0。

因此,您分别从表A和B中有选择地智能地选择了人i和j,以使总体评级发生最佳变化,然后继续进行直到没有更好的解决方案为止。

该算法的缺点是步骤1:您需要计算所有总体评分变化。但是,即使有1000个表,这也不是问题。

独特的解决方案?

很多时候,您可以找到针对此问题的多种解决方案。想象一下,您发现了上述算法的一种解决方案。那么,在2个人之间进行的任何切换都会使总体变化为0,这是另一种解决方案。因此,找到1个解决方案,就很容易找到所有解决方案。

如果找到1个解决方案,并且发现开关的总体额定值更改为0,因此是一个新的解决方案,则可以使用该新解决方案来找到另一个解决方案,依此类推。想象每个人都设置相同的权重(例如,没有人在乎,所有权重都为0),那么任何设置都是一种解决方案。

我希望这会有所帮助。我知道这是一个很长的解释,我希望它足够清楚。如果您需要更多详细信息,请告诉我。