【问题标题】:item placement algorithm物品放置算法
【发布时间】:2011-09-23 18:32:39
【问题描述】:

因此,我正在寻找一种确定物品放置位置的算法,但是,我很难将我的测量形式化为一个位置的“好坏”。

问题出在:我有一组k 想要沿一条线放置的项目。每个项目都有一个宽度,没有两个项目可以重叠。每个项目也有一个对应的区间——所有区间都是固定的、不重叠的,并且形成了线段的一个分区。

我想放置每个项目,使其在其间隔中居中,但我不能保证间隔比项目宽。

因此,作为妥协,我愿意将项目部分(或全部)移出它们的间隔。但是,我不愿意更改项目的顺序(它们必须保持间隔的顺序)。

是否有一个很好的算法可以根据我的(松散定义的)度量找到沿线的项目“最佳”位置?

【问题讨论】:

  • 考虑两个项目,(a=0-10) 和 (b=1-2),应该先出现哪个?
  • 只是对问题的观察:由于间隔不重叠,并且您愿意将项目移出间隔,因此间隔似乎并不重要,只有它们的中心才重要。您可以只为每个项目提供一个“理想位置”的问题,说您希望保留订单等。
  • @ShreevatsaR:你是对的;我怀疑 OP 的约束条件比他们提到的要多。要么这样,要么这是旨在确定他们是否能抓住你的准确观点的家庭作业。
  • @ShreevatsaR:+1 有效点。我的意思是说,将项目保持在它们的间隔中比不更可取(因此一旦完全超出间隔,善度会随着距离而更快地下降)但忘记提及了。
  • 您可以尝试使用KKT conditions 来最小化从对象中心到其相应间隔中心的距离总和。您可以使用不等式(即距离大于半径之和)对非重叠条件进行建模

标签: algorithm language-agnostic


【解决方案1】:

嗯,这可能是我可以解释您的问题的最简单方法的解决方案:

让我们假设对于每个项目,我们考虑两种可能性:

  1. 我们将其放置在预期的位置(即区间的中心)

  2. 我们没有

然后,我们可以将这个问题重新表述为以下函数:找到可以放置在其区间中心而不重叠的项目的最大子集合。

这似乎应该有一个贪婪的解决方案,但我必须承认,我能做的最好的事情就是想出一个非常幼稚的动态规划算法。以下是我制定复发的方法:

假设我们正在考虑第 n 个项目(从左边开始),并且我们想要分配它,使得该项目的左边缘不超过所有前面项目的最右边。那么,最优分配必须满足:

best_align(n, right) = 
     if center[n]-radius[n] > right[n]:
          max(best_align(n+1, right+radii[n], 1+best_align(n+1,center[n]+radius[n])
     else:
          best_align(n+1, right+radius[n])

这有一个明显的 DP 解决方案,我编写了(在 python 中)。结果如下:

#Assumes that the items are sorted left-to-right by their centers
def best_align(radii, centers):

    assignments = { (radii[0]+centers[0]):[0], (-100000):[] }

    for i in range(1, len(radii)):

        nc = centers[i] + radii[i]
        nassignments = { nc : [i] }

        for right, assigned in assignments.items():

            #Handle case where object is not inserted
            nr = right+radii[i]
            if not nr in nassignments or len(assigned) > len(nassignments[nr]):
                nassignments[nr] = assigned

            #Handle inclusion case
            if right <= centers[i]-radii[i] and len(assigned) >= len(nassignments[nc]):
                nassignments[nc] = assigned + [i]


        assignments = nassignments

    return max([ (len(l), l) for l in assignments.values() ])[1]

变量radii是各个item的半径,center是目标赋值位置。该算法返回可以放置在所需位置的项目的最大子集。剩下的项目只需要尽可能地捏造。例如,这里有一些输出:

在 [11] 中:plc.best_align( [ 1, 5, 1], [0, 2, 3] )

输出[11]:[2]

另一个例子:

在[18]中:plc.best_align([1, 10, 1, 1, 1, 1, 1], [0, 2, 4, 6, 8, 10, 12])

输出[18]:[2、3、4、5、6]

由于处理分配集的简单方式,此实现的时间复杂度是三次方。人们可以通过将 python 列表替换为返回到它们所构建的先前列表的引用来轻松优化以获得二次解(尽管这会使演示文稿更糟糕)。

【讨论】:

    【解决方案2】:

    这听起来像是一个松散耦合的约束系统。粗略地说,您可以通过深度优先搜索约束元素的相关约束来找到“最佳”放置(不保证是“最佳”,但应该是“功能性”)。

    让我描述一下。第一次运行时,尝试将所有元素放置在其间隔的中心。检查以查看重叠的对象。当你遇到一个重叠的物体时,暂时将那个物体从重叠处移开;检查该系统是否有重叠。重复所有重叠。

    这将根据间隔的顺序保留对象的顺序。如果需要的话,应该可以通过与区间的分歧量来“评分”每次迭代的值,以尝试最小化与区间的距离。

    【讨论】:

    • 如果项目 a、b 和 c 相邻,并且所有三个都重叠,该怎么办?我不清楚 b 会发生什么,但不知道 a 和 c 会发生什么,这取决于他们的其他邻居。
    猜你喜欢
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 2019-03-08
    • 2012-12-26
    • 1970-01-01
    相关资源
    最近更新 更多