项目放置算法

时间:2011-06-27 19:12:24

标签: algorithm language-agnostic

所以我正在寻找一种确定项目展示位置的算法,但是,我很难将我的度量标准化为一个位置的“好”。

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

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

所以,作为妥协,我愿意将项目部分(或完全)从他们的间隔中移出。但是,我不愿意改变物品的顺序(它们必须保持间隔的顺序)。

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

2 个答案:

答案 0 :(得分:1)

嗯,这是解决问题的最简单方法:

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

  1. 我们将它放在预定的位置(即间隔的中心)

  2. 我们没有

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

    这似乎应该是一个贪婪的解决方案,但我必须承认,我能做的最好的事情是想出一个非常天真的动态编程算法。以下是我如何制定复发:

    假设我们正在考虑第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]
    

    变量半径是各种项目的半径,而中心是目标分配位置。该算法返回可以放置在所需位置的项目的最大子集。其余的项目必须尽可能地捏造。例如,以下是一些输出:

      

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

         

    Out [11]:[2]

    另一个例子:

      

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

         

    Out [18]:[2,3,4,5,6]

    由于处理分配集的天真方式,此实现的时间复杂度是立方的。通过将python列表替换为它们构造的先前列表,可以很容易地优化以获得二次解决方案(尽管它会使表示更糟糕)。

答案 1 :(得分:0)

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

让我来描述一下。对于第一次运行,尝试将所有元素放在它们的间隔中心。检查是否有重叠的对象。遇到重叠物体时,暂时将物体移离重叠物;检查该系统是否有重叠。重复所有重叠。

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