在电影院安排座位

14

这篇文章基于我读到的一个有关大型软件公司面试中难题和提问的文章,但它有点不同...

一般问题:

如何安排电影院里的座位,使得朋友们直接坐在一起,但不与敌人相邻?

技术问题:

给定一个N*M的网格,在此网格上填充N*M-1个项目。每个项目对其他N*M-2个项目都有一个布尔值关联。在每行N上,相邻的项目应该对其他项目具有积极的关联值。然而列并不重要,也就是说,一个项目可以与其前面的项目“为敌”。注意:如果项目A对B具有积极的关联值,则意味着B对A也具有积极的关联值。负关联值同样适用。保证每个项目至少与另一个项目有积极的关联。同时,您可以在开始放置它们之前访问所有项目及其关联值。

评论:

我已经研究了这个问题并思考了它自昨天以来,从我发现的情况来看,它让我想起了装箱问题,但加了一些要求。在一些空闲时间里,我尝试实现它,但是大量的“敌人”坐在一起。我相信大多数情况下至少会有一对敌人坐在一起,但我的解决方案远未达到最优。实际上,看起来就像我只是随机排列了它们。

就我的实现而言,我将N=10、M=10、项目数=99,并为每个项目创建了一个大小为99的数组,其中包含一个随机化的布尔值,用于引用相应项目编号的友谊关系。这意味着每个项目都有一个与自己对应的友谊值,我只是忽略了该值。

我计划稍后尝试重新实现这个,并发布代码。有没有人能够想出一种“好”的方法来最小化敌人之间的座位冲突?


1
这让我想起了电子元件的放置算法。我会尝试几次,然后使用某种评估算法选择“最佳”方案。这是我解决“放置”问题的一般方法,这些问题非常适合迭代计算解决方案,而不是直接使用数值公式。 - John
1
我认为这是……如果Andersk想要看比赛,要么把他安排在柱子后面,要么安排在带着大帽子并且拒绝脱掉的人后面,因为天气太冷了。 - AndersK
4
好无聊!把人们安排在一起,最大程度地制造敌对冲突会更加刺激。 - Peter Olson
1
这绝对是NP难问题,因此-目前没有已知的多项式解法,您是否还在寻找针对此问题的证明?或者您是否已经知道了这个事实,并在这些限制范围内寻找解决方案?目前您最好的解决方案是什么? - amit
这个问题可能会在MathematicsComp Sci Theory找到更好的答案,因为它与编程关系不大。 - Igby Largeman
显示剩余4条评论
2个回答

9
这个问题是NP-Hard的。定义L={(G,n,m)|在m×m矩阵中有一个合法的G座位,(u,v)∈E,如果u是v的朋友} L是该问题的正式语言定义。 证明:
我们将用2步骤展示哈密顿路径问题 ≤ (p) 2路径问题 ≤ (p) 这个问题 [哈密顿路径和2路径的定义如下],从而我们得出结论,这个问题是NP-Hard的。
(1) 我们将展示找到两条覆盖所有顶点的路径,而不使用任何顶点两次是NP-Hard的[让我们称这样的路径为:2-path问题]
哈密顿路径问题进行约简:
input: a graph G=(V,E)
Output: a graph G'=(V',E) where V' = V U {u₀}.

正确性:

  • 如果G有哈密顿路径:v₁→v₂→...→vn,则G'有2路径: v₁→v₂→...→vn,u₀
  • 如果G'有2路径,则由于u₀与其余顶点隔离,存在一条路径:v₁→...→vn,在G中是哈密顿路径。

因此:G具有哈密顿路径1 ⇔ G'具有2路径,因此:2路径问题是NP-Hard。

(2)我们现在将展示[L]问题也是NP-Hard的:
我们将从上面定义的2路径问题进行归约。

input: a graph G=(V,E)
output: (G,|V|+1,1) [a long row with |V|+1 sits].

正确性:

  • 如果G有2路径,那么我们可以安排人员,并使用1个座位间隙作为两条路径之间的“缓冲区”,这将是合法的完美座位,因为如果v₁坐在v₂旁边,则v₁ v₁→v₂在路径中,因此(v₁,v₂)在E中,所以v₁,v₂是朋友。
  • 如果(G,|V|+1,1)是合法的座位:[v₁,...,vk,buffer,vk+1,...,vn],则G中存在2路径,v₁→...→vk,vk+1→...→vn

结论:该问题是NP-Hard问题,因此没有已知的多项式解决方案。

指数解决方案: 您可能想使用回溯解决方案:基本上是:创建大小为|V|-2或更小的所有E子集,检查哪个最好。

static best <- infinity
least_enemies(G,used):
  if |used| <= |V|-2:
     val <- evaluate(used)
     best <- min(best,val)
  if |used| == |V|-2: 
     return
  for each edge e in E-used: //E without used 
     least_enemies(G,used + e)

在这里,我们假设evaluate(used)给出了此解决方案的“分数”。如果此解决方案完全非法[即一个顶点出现两次],则evaluate(used)=infinity。当然可以进行优化,修剪这些情况。为了获得实际的解决方案,我们可以存储当前最佳解决方案。
(*)可能有更好的解决方案,这只是一个简单的可能的解决方案,本答案的主要目的是证明这个问题是NP-Hard。
编辑:更简单的解决方案: 创建一个图G'=(V U { u₀ } ,E U {(u₀,v),(v,u₀) | for each v in V}) [u₀对于缓冲区是一个垃圾顶点]和边的权重函数:
w((u,v)) = 1    u is friend of v
w((u,v)) = 2    u is an enemy v
w((u0,v)) = w ((v,u0)) = 0

现在您已经拥有一种经典的TSP,可以使用动态规划在O(|V|^2 * 2^|V|)中进行求解。请注意,这种使用TSP的解决方案仅适用于单行剧院,但可能是解决通用情况的良好线索。

0

对于像这样的大型“搜索空间”,使用的一种算法是模拟退火


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接