基本上,假设我有5个具有以下宽度的项目(高度对此并不重要,所以让我们说它们都有50像素的高度):
我希望尽可能将它们分成两行(必须按顺序排列)。如何计算行的最小宽度?
注意:这并不像添加所有宽度并将其除以行数那么简单,如果您使用上面的示例执行此操作,则项目将不适合因为总和宽度(400)除以行数(2)为200(400/2 = 200),在这种情况下,第五项不适合任何行。
如果使用我刚才提到的方法,这是另一个不起作用的例子:
在这种情况下,最后两个项目(5和6)需要一个额外的行。
C#示例非常好,因为它是我用来做这个的语言=)。
谢谢!
答案 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)
如果订单是固定的并且恰好有两行,这是一个相当容易的问题。将宽度数组转换为累积数组。对于第一个例子,它将是:
第二个是:
然后只搜索最接近最后一个条目一半的条目,并在该条目之后将列表分成两个。任意解决关系(因此,在任何一个例子中,在第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