在座位图中分配连续的座位

时间:2011-11-06 08:20:58

标签: algorithm

我必须在座位图中编写一个分配连续座位的算法。例如:在体育场内分配座位。座位图可以被视为N行和M列的2d阵列。系统必须为一起制作的预订分配连续的席位。由于没有向用户呈现座位图,系统应自动分配与每次购买相对应的可用座位。除此之外,它应该以这样的方式做到这一点,使座椅中的孔/间隙最小化。

4 个答案:

答案 0 :(得分:4)

找到一个完美的解决方案是NP-hard。看看等效的语言问题:
L={((x1,x2,...,xk),n,m)}其中xi是共同预订的门票数量,n,m是体育场规模。

我们将显示Partition< =(P)L,因此这个问题是NP-Hard,并且没有已知的多项式解。

<强>证明
S=(x1,x2,..,xk)作为分区问题的输入,让sum=x1+...+xk
看下面的减少:

Input: S=(x1,...,xk)
Output:((x1,...,xk),sum/2,2)

<强>正确性: 如果S有一个分区,那就让它为S1=(x_i1,x_i2,...,x_it),然后根据分区的定义x_i1+...+x_it=sum/2,这样我们就可以在第一行插入x_i1,..,x_it,其余的在第二行,所以((x1,...,xk),sum/2,2)在L中
如果((x1,...,xk),sum/2,2)在L中,那么根据定义,有{t}预订,x_i1,x_i2,...,x_it形成一个完美的第一行,因此x_i1+x_i2+...+x_it=sum/2,因此它是一个有效的分区, S处于分区问题

<强>结论: 由于L是NP-Hard,你所寻求的问题是这种语言的优化问题,因此没有已知的多项式解。对于一个精确的解决方案,您可以使用backtracking [检查所有可能性,并选择最佳],但这将花费很多时间,或者您可以尝试启发式解决方案,例如greedy,但它不会被优化。

编辑:回溯解决方案[伪代码]:

solve(X,n,m):
   global bestVal <- infinity
   global bestSol <- null
   solve(X,new Solution(n,m))
solve(X,solution):
   if (X is empty):
       gaps <- solution.numGaps()
       if (gaps < bestVal):
            bestVal <- gaps
            bestSol <- solution
       return
   temp <- X.first
   X.removeFirst()
   for i from 0 to m:
       solution.addToLine(i,temp)
       solve(X,solution)
       solution.removeFromLine(i,temp)
   X.addFirst(temp)

假设Solution是一个已实施的类,并且是非法解决方案[即一行中的人太多了numGaps() == infinity

答案 1 :(得分:0)

注意

这通常不是一个真正的问题,因为如果您能够出售所有门票 - 最后的买家要么妥协并将其预订分成单独的预订,要么退出,并允许其他具有不同预订大小要求的买家买剩余的座位。

此外,人们喜欢选择自己的座位。如果你想禁止这个选项 - 他们可能会选择不买票。

请注意,如果买家无法控制他们的座位,您也可以给他们一个代码,并在售出所有门票后将此代码翻译成特定的座位。

回答所提出的问题:

每行都有 m 个席位。我们假设最大的预订大小是 m (否则,我们将不得不将其分成几个预订)。

首先,我们应该为预订大小建模离散概率分布函数。这可以基于来自先前事件的数据来构建。 (更高级的模型可以考虑事件类型,事件时间等)。我们将此函数称为 f(b)

最好的策略是从左到右(或从右到左)填充行,而不是留下空隙 - 这只会迫使更多的约束。

这是微不足道的。

让我们假设体育场包含一排。我们可以通过列举所有可能的预订大小来计算填充整行的概率。我们可以使用建议here的方法进行枚举,将每个预订大小乘以其概率,并将其相加。

现在,假设体育场中有2行,第一个预订大小为3.现在有一排 m 空座位,另一行 m -3 空座位。第二个预订大小为4.现在我们可以比较填充(m-4)座位行的概率和填充(m-3-4)的概率座位排。我们将相应地为当前预订分配座位。

当然,填充空行的概率是1,一旦填充,它应该从未填充的行列表中删除。

一般而言,对于每次预订,我们都可以将其分配到填充它的概率(在分配之后)最大化的行。

请注意,给定 f(b),所有这些概率都可以预先计算 1 m 之间的任何常数。

答案 2 :(得分:-1)

您应该查看操作系统的内存分配算法。这最能模拟您的问题。你应该专注于最小化碎片的算法。

答案 3 :(得分:-1)

我喜欢最后一个。从最简单的意义上讲,他是非常正确的。对于速度,概率图测试是填充行的好方法。但它缺少一些元素。你是否关心派对是否被多个席位分开?取消和退款怎么样?看一下这个问题有点不同。有3种可能的状态,而不是2. M个空座位,R行,每个有3种可能的状态:空置,填充,已取消,其中已取消有调整后的概率。你怎么处理?您可以通过将其设置为新行来增加填写取消或退款的概率,所有这些都是N个座位,填充1到N个席位的概率为1,您可以进一步增加填写所有当N> 1时,通过限制可能的方大小来限制座位。 2,参与方大小> 2但小于N.

另一种方法是使用地图。为了说明,创建一个关于座位化的小方块的电子表格。现在突出显示区域并用外框线条绑定它们。这些是您的行和列部分。在每个座位上放置一封信,表明座位可用性。现在创建一个链接到该文件的数据库。您可以添加一个部分来定义行中座位的编号,然后根据该部分识别场地的票号,并​​且可以运行简单的测试来填充座位。它将&#34;最小化&#34;差距,但可能不会完全消除它们。如果像我一样,你与showpeople \ entertainers \音乐家和场地合作,那么映射是关键。我工作的主要群体很小,并且拥有忠诚但不断变化的追随者。这是一个儿童计划,社区外展和表演小组。我遇到的问题是很多人都想和朋友一起坐等等。所以我想出了多票\​​ ROW \ TABLE攻击计划。你怎么处理这个? 对于您所做的每个部门,您必须在编程中做出规定。行和列很适合使用。我们从那里开始。使用表格,将它们放入行和列中,您可以很好地剪切它们。它可能并不完美,但它确实有效,对你所做的每个分段进行一点调整。

考虑一下...... 简单地从左到右编号你的座位。实际为故障单分配座位时,请遵循以下模式: 对于一列a a left - &gt; right(以直线填充座位)            一行b向右 - >向左(现在按照下面的数学运算) 对每一列做同样的事情(把它想象成卡内基厅的场地,每一列每侧都有过道,并且排成几排)。列中每行的数学运算是相当基础的。对于团体预订,取偶数行中的总座位数为:如果是partysize&gt; remainingSeatsInRow mult seat#_in_row by -1然后添加到座位#_Normal = S(其中S是座位#_within_row),如果S * -1> 0,S * -1 = S endif,那么场地按群组填充并且通过单一,将各方保持在一起。现在向您介绍几个循环... ...假设您每15行调整一次定价,那么较高的价格区域可能会填满较慢,因此您可以添加激励但仅适用于这些区域,或调整激励对于每个区域和该区域中可用的票数等等。现在添加检查剩余座位的其他定价区域的能力以容纳一个小组(记住,他们只需要在同一区域,他们仍然会靠近一起坐在一起;我会专注于列操作只对节省时间,但每个人自己),现在你甚至可以发送一个请求,以更低的价格填补更高价格区域的空座位,只是为了填补场地附近的场地,让人们满意他们的朋友。现在可供选择......如果有可用的座位,您可以让人们选择他们的位置。在我建造的情况下,场地会像日期一样变化,所以我必须针对它的所有肌肉展示这个算法。基本上,表演是慈善工作,人们是父母,朋友,社区成员等,知道团体表演和相互了解。如果他们知道有人坐在哪里,他们就会想要亲近。获取他们想要的门票数量,并按照您想要的任何设置显示具有多个座位的区域;你甚至可以通过行和列(使用你的座位填充示例;卡内基有几组通道在行之间分隔一列,所以你可以改变列,或者只是继续卡车通过;卡内基也有平坦的座位和阳台 - 正如年轻的辛普森先生所说,&#34; Aye Carumba!&#34 ;;每个场地都有不同的设计布局,如果你改变了,你必须做一个在你的数据库中计划它并从中工作;这个模型很灵活,因为它可以调整到几个图表)无论如何,为了正确使用:使用原始测试在这里直线(你可以让他们选择列和他们的伙伴排,然后测试列,然后测试相邻行的相邻列的座位#&#39; s测试接近度,使用上面的原始邻近守护者的数学,如果左边的伙伴,测试左列在右边的座位上,如果是右边的好友,请查看左侧座位上的右栏#,甚至比较后面讨论的取消r ,原始测试的操作数只是交换位置或者你可以翻转它等等)如果你突出显示座位打开的区域,然后从它们那里得到一个数字,然后只突出显示有那么多的区域可用的连续座位(如果需要,在2行或更多行上运行测试,再次在列的行中实现与上面相同的测试),如果您正确地进行了上述测试,他们很可能会坐在一起,但是在最糟糕的情况下,他们会坐在尽可能接近的地方(这次测试的频率是多少,是吗?只要您有足够的空间填写,您可以选择提供特殊价格的选项,但从逻辑上讲,您应该在此辅助展示位置可容纳的partysize上设置上限,并且很可能会更频繁地失败,因为您越来越接近你的表演时间 现在来了有趣的部分,差距清理。有些人会因为在工作或交通上而迟到或者可能会迟到,并希望看到一个节目或看到他们的孩子对彼得潘进行荒谬的演绎。如果您在任何特定行或列中的免费座位数为1并且它们周围没有座位(如果人们取消将会发生这种情况),或者您已取消整个群组,则需要将这些座位放回排序帽中。这有几种方式。您可以为每个部分创建一个大型的座椅阵列并从中进行操作,但最好只打开一个新的列表来容纳可填充主要座位的小型相邻座位阵列;或者,您可以创建一个座位图文本文件,将每个座位标记为空,完整,取消并存储已取消组的指针,然后在每次取消后测试取消映射,并为包含该组的不同组大小创建单独的映射每种尺寸的座位列表。您可以使用VenueTitle_Cancel_GroupSize命名地图,然后对测试进行编码,以检查GroupSize为&gt; =的所有地图到您的新组。这样可以更好地找到你的伙伴,因为你有一个新的测试,但是你可以使用相同的预测试来排列这些,以便扫描可用的座位并进行绘制:测试是否有任何取消,测试每次取消的连续座位数量(新组中有多少人?他们是否适合取消位置?在取消位置的剩余座位上给他们打折,然后处理所有输入)......这不是一个算法,甚至没有关闭,只是一个心理设计的问题与大量的IF风格的基本算术测试,应该像闪电一样运行,但你可以通过分离运行它们的机器拆分这些测试,并等待所有进程回来,然后将结果一起添加等,(旧学校多服务器查询远程文件,远程计算机托管的数据库查询软件;使用较新的服务器,您可以通过在XSERVE中将它们绑在一起来更快地运行测试,并设置处理这些测试的多宿主服务器场数据,小处理网络前沿的单位。)

规划:    弄清楚如何划分您的场地,然后弄清楚如何编号\计算不同的部分\座位以及如何定价,然后弄清楚您是否希望人们通过交互式视图选择价格,或者简单的一个。如果有更多的互动,你可能会遇到一些差距。如果有其中一些,您可以通过座位列表向相关方提供价格下降或特别邀请等。这使您可以建立场地的最大化,并提供最大化满意度的选择。不确定调用该算法的是什么,但使用冒泡排序,数据库或任何类似的算法可以让您设置票证价值以及预订所需的所有信息。这允许您将取消作为单独但已链接的项目进行处理,设置标记,并重复向您的操作添加数据处理,以防止超出或低于预订。执行此操作的基本方法是:如果您超量预订,您将获得每个最后交易的时间标记,N + 1(其中N是超额预订交易的数量),以及最后一次预订后的所有人(填充场地或仅())将设置为具有相同交易信息的新表格,然后检查它们是否仍然适合,如果没有,它们将被退还,通过电子邮件发送或电话。这样,您可以检查可用座位的数量,看看是否有人想缩短他们的聚会。您还可以通过将其信息导出到CMS的新表格来向他们提供新的优惠,并让他们满意。这需要做很多工作,但如果设置和处理得当,这种方法可以运行多个并发测试。 这可能是一个冗长而枯燥的答案,但是归功于Lior,他有一个常用的测试说明。如果您具有处理能力和构建代码的时间,那么这只是我的最大化程序。