【问题标题】:Calculating the optimal number of columns for a table layout - Only given the table width and a list of rectangles计算表格布局的最佳列数 - 仅给定表格宽度和矩形列表
【发布时间】:2011-04-18 21:17:41
【问题描述】:

我有一个不同尺寸的矩形列表。

rects = [100x20, 30x10, 10x10, 70x20, 40x30, 50x10]

我正在尝试从这些矩形中呈现一个表格。如果我有固定数量的列,我可以简单地计算行数和每行和每列的大小,如下所示:

numCols = 4;

for (i = 0; i < rects.size - 1, i++):
    rect = rects[i];
    col = i % numCols;
    row = floor(i / numCols);

    columns[col] = max(columns[col], rect.width);
    rows[row] = max(rows[row], rect.height);
end for;

现在我希望我的表配置为最大行宽。列数取决于最佳行宽的运行时计算。

根据上面的列表和设置为 140 的最大行,我希望我的表是:

rects = [100x20, 30x10, 70x10, 10x20, 40x30, 10x10]

100x20, 30x10
70x10, 10x20
40x30, 10x10

cols = [100, 30]
rows = [20, 20, 30]

我处理这种情况的第一个想法是为每个可能的列数缓存最大列宽。最后一个总和

max[1] = [100]
max[2] = [100, 30] - wins
max[3] = [100, 40, 70] - 210 > 140
max[4] = [100, 30, 70, 10]
max[5] = [100, 30, 70, 10, 40]
max[6] = [100, 30, 70, 10, 40, 10]

不幸的是,我需要为每个可能的列号创建一个 max 条目。该列表可能会变得非常大。有人知道解决这个优化问题的算法吗?

【问题讨论】:

  • 也许你可以添加更多关于你的算法应该解决的问题的细节。您究竟想要优化什么(行数、表格高度)?例如。你的方法给出了 max[2]=[100,10] 而你的例子是 [100,30]。为什么更喜欢第一个?在您的示例中,您永远不会更改矩形的顺序。这是一个要求吗?标题也声明“大小均匀”,但您从未在描述中提及这一点。如果我们对目标有更多了解,我想我们可以找到一个(已知的)算法。
  • 最大数组的“相当大”有多大?这似乎是一种明智的做法,贪婪地取最宽的矩形,然后从左边开始放入列中(最宽的矩形必须放在某个地方,你最好尽可能多地利用它下面的空间)。您不必存储最大数组,只是迄今为止最好的数组,计算给定列数的行宽很简单(如果您只是按宽度递减的顺序对矩形进行排序,这是一个快速循环和添加)。如果我正确理解问题,我会将其移至答案。
  • @Howard,你说得对,max[2] = [100, 30]。我已经更新了示例。
  • 想象一下这个问题,在一个只给定最大宽度但没有列/行数的表格中显示一个不同大小的缩略图列表。缩略图的顺序很重要。表格的高度是无限的,但最佳解决方案会产生最少的行数。
  • @Howard,“大小均匀”只是意味着一列中的单元格应该具有相同的宽度。项目可能小于其封闭单元格。

标签: algorithm tiling


【解决方案1】:

我只能看到对您的解决方案的优化:

假设:
MaxAllowedWidth - 所有列宽度的最大允许总和

  1. 在寻找可能的解决方案(您的最后一个表)时,当总列宽将超过 MaxAllowedWidth 时,停止尝试添加新列。在您的示例中,您应该在第三步停止并且不要尝试 4、5、6 列,因为 3 列已经占用了您允许的更多空间。请注意,在此步骤中,我们仅考虑第一行项目。

  2. 以相反的顺序遍历上一步中可能收到的列号。第一个适用的解决方案将是最佳的,因为它将具有尽可能少的行数。

  3. 在第 2 步中,您应该检查此列数是否真正适合您的 MaxAllowedWidth。在您的示例中,您将从总宽度 = 130 (100 + 30) 开始。然后浏览这些列,您应该检查是否应该扩大该特定列。如果列应该被放大,那么检查放大的列是否会占用比你剩下的更多的空间。如果它会尝试使用较少列的解决方案。此检查将允许您提前退出并跳过无用的迭代/操作。

问题描述不是很清楚,直到我阅读了cmets,我才知道你想要什么。 max row width 对我来说毫无意义,total columns width 听起来更好,IMO。

【讨论】:

  • 斯帕西博雪熊!可能的列数可以这样划分:添加最宽的项目直到达到MaxAllowedWidth 会给出适合的最小列数。然后取最宽的项目并添加最低的项目,直到达到MaxAllowedWidth 可以得到最大的列数。给出宽度为 1、...、100 和 300 的 MaxAllowedWidth 的随机列表,可能的列数范围为 4 到 20,而 3 (100+99+98
  • 我认为您甚至不需要考虑minimum 的列数。因为在此任务中,可能会出现某些列不适合的情况,但放入 more 列会有所帮助。示例是 rects: [1, 1, 100, 1, 1, 100] 和 maxAllowedWidth=150。在这种情况下,两列不适合,因为它们都应该具有100 宽度,但三列将适合,因为两个最大的项目将进入同一列。所以我认为您不必担心最小列数。
  • 如果没有其他可能性满足,则最小值为断点。
  • 好吧,下一个见解:创建表是一种开销。无论如何,在运行时和按需计算最大列宽更便宜。优化现在朝着限制最大可能列数的方向发展。什么启发式可以帮助?测量紧挨着最宽的项目可以比考虑上面所说的最小项目提供更好的预测:[1,1,1,100,1,100,1,1,1] 和maxAllowedWidth=150 使用第一个“100”将最多给出 2 列 (100+1)。最小方法改为返回 (100+1+1+1+1+1+1+1) 8 列。
  • @Jens,如果您不允许重新排序项目(如您所说),那么计算最大列数的一种方法是在总宽度小于 MaxAllowedWidth 时获取项目。在此示例中,直到找到第二个 100 元素。
【解决方案2】:

为了完成这个问题,这里是实际的表格布局。你可以设置一个最大宽度,列数是根据这个线程中讨论的算法计算的:

http://sibirjak.com/osflash/projects/as3commons-ui/layouts/showcase/#a6-dyntable

编辑:

要修改盒子的数量,请从示例 Flash 窗口底部的任务栏打开盒子窗口。

【讨论】:

    猜你喜欢
    • 2018-01-25
    • 1970-01-01
    • 2021-08-29
    • 2011-04-06
    • 2018-08-19
    • 2014-05-22
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    相关资源
    最近更新 更多