以固定行数拆分不同宽度的项目

时间:2012-05-30 19:47:32

标签: algorithm

基本上,假设我有5个具有以下宽度的项目(高度对此并不重要,所以让我们说它们都有50像素的高度):

  1. 50
  2. 100
  3. 100
  4. 100
  5. 50
  6. 我希望尽可能将它们分成两行(必须按顺序排列)。如何计算行的最小宽度?

    注意:这并不像添加所有宽度并将其除以行数那么简单,如果您使用上面的示例执行此操作,则项目将不适合因为总和宽度(400)除以行数(2)为200(400/2 = 200),在这种情况下,第五项不适合任何行。

    如果使用我刚才提到的方法,这是另一个不起作用的例子:

    1. 100
    2. 50
    3. 100
    4. 50
    5. 50
    6. 50
    7. 在这种情况下,最后两个项目(5和6)需要一个额外的行。

      C#示例非常好,因为它是我用来做这个的语言=)。

      谢谢!

3 个答案:

答案 0 :(得分:3)

假设您正在尝试在宽度N的{​​{1}}行中放入{W[i]}宽度为R的项目;您的C已修复,R未知。

首先,让我们做一些重要的观察:

  • 如果选择C,如果选择特定的C将您的排列设置为C行,则很容易检查:您可以通过逐个项目,计算运行总计,并使用R作为截止点。
  • C的最小值是最小C;最大值是W[i] s
  • 的总和
  • 增加W[i]可以使C所需的行数减少,但不能使其上升;因此,函数C单调

这些观察导致了一个简单的算法:通过在二进制搜索的每一步基于运行总计运行检查器,对最小RequiredRows(C, W[0..N])运行二进制搜索,使C

这是C#中的骨架实现:

RequiredRows(C, W[0..N]) == R

答案 1 :(得分:1)

如果订单是固定的并且恰好有两行,这是一个相当容易的问题。将宽度数组转换为累积数组。对于第一个例子,它将是:

  1. 50
  2. 150
  3. 250
  4. 350
  5. 400
  6. 第二个是:

    1. 100
    2. 150
    3. 250
    4. 300
    5. 350
    6. 400
    7. 然后只搜索最接近最后一个条目一半的条目,并在该条目之后将列表分成两个。任意解决关系(因此,在任何一个例子中,在第2项或第3项之后)。然后,最小行宽是条目累积宽度的最大值或者与总宽度之间的差值(最后一个累积条目)。

答案 2 :(得分:0)

考虑你想要两行的情况。您可以只测试列表中所有可能的分割点(索引),看看哪一个产生最佳结果(最小化最大行宽)。

对于两行以上,只需使用递归来继续分割"右半部分"如下面的代码示例所示。 (Python)的

def split(sizes, count):
    # base case: one row, just return it
    if count == 1:
        return [sizes]
    best_score = None
    best_result = None
    # for each possible split point (don't allow empty rows)
    for i in range(1, len(sizes)):
        # the first row is the columns up to the split point
        left = [sizes[:i]]
        # recurse to process the remaining rows
        right = split(sizes[i:], count - 1)
        if right is None:
            # failed to split count - 1 times, ignore
            continue
        rows = left + right
        # minimize the maximum row width
        score = max(sum(row) for row in rows)
        if best_score is None or score < best_score:
            best_score = score
            best_result = rows
    return best_result

if __name__ == '__main__':
    sizes = [100, 50, 100, 50, 50, 50]
    print split(sizes, 2)
    print split(sizes, 3)

输出:

[[100, 50], [100, 50, 50, 50]] # 2 rows
[[100], [50, 100], [50, 50, 50]] # 3 rows