一开始,我尝试将其视为排序问题。但我认为将其视为优化问题更好。让我试着形式化这个问题。给定:
- wi:杆i的重量
- li:杆i的长度
- mi:杆i距离原点的最大距离。如果没有限制,可以将此值设置为sum(i=1,n, li)
问题是找到一个排列ai,使得成本函数:
J=sum(i=1,n, wai*sum(j=1,i-1, laj))
最小化,并满足约束条件:
sum(j=1,i-1, laj) <= mi, 1 <= i<n
。
我不确定这是正确的表述。没有任何限制条件,最优解并不总是按重量排序的杆子。例如,令l={1,4},w={1,3}。如果a={1,2},则J为1*0+3*1=3,如果a={2,1}(按重量排序),则J为3*0+1*4=4。显然,未排序的解最小化成本函数,但我不确定这是否符合您的要求。
此外,我还不知道如何解决这个问题。您可以尝试在短期内进行某种启发式搜索。我正在撰写这篇改写,以便其他人可以在我思考更多解决方案的同时提供解决方案。如果它是正确的,当然。
另一个需要注意的事情是,您不必找到完整的解决方案来查看是否有解决方案。您可以忽略没有位置约束的杆子,并尝试仅使用受约束的杆子解决问题。如果存在解决方案,则该问题确实有解决方案(明显的次优解是对无约束杆进行排序,并将其附加到减少问题的解决方案中)。
说了这么多,我认为下面的算法可以解决问题。我会用一些视觉上的描述来使它更容易理解。想法是根据您的问题描述,从左到右(原点是线段的最左端点)在线段上放置杆子。
- 将带有位置约束的杆子分开。然后,将它们放置在其约束位置的极限处。
- 如果没有重叠的杆子,请转到步骤4
- 对于每对重叠的杆子,将较靠近原点的向原点移动,以使它们不再重叠。这一步可能需要将直线上的其他杆子向原点移动以打开一些空间。通过检查移动后的杆子是否与其左侧的杆子重叠来检测此情况。如果您无法创建足够的空间(将最靠近原点的杆子移动到0仍然无法释放足够的空间),则无解决问题的方法。在这里,您有机会通过放松原始重叠对的最右边的杆子的约束来找到解决方案:将其移离原点,直到没有重叠(在执行此操作之前,您可能需要将先导杆向右推,直到解决所有重叠为止)。
- 现在,我们已经放置了一些杆子,并且周围有一些空闲空间。开始用最重的杆子(包括那些在空闲空间右侧的约束杆子)填充空闲空间。如果找不到适合的杆子,则只需将空闲空间右侧的下一个杆子移动以关闭间隙。
- 重复步骤4,直到达到最右边的约束杆。剩余的线段均为自由空间。
- 按重量对所有剩余的杆子进行排序,并将它们放置在剩余的自由空间中。
关于算法的一些注释:
它不能解决我之前提出的问题。它只是尝试根据杆的重量对其进行排序。
我认为有一些失去的机会可以做得更好,因为我们将一些杆向原点滑动以使它们全部适合(在步骤3中),有时从这些“挤入”的地方选择重杆,并将它们靠近原点(在步骤4中)。这释放了一些空间,但我们没有将被推开的杆滑回到其受限制位置的极限。这可能是可能的,但我需要在我的大脑工作得更好时修改算法。
这不是一个非常高效的算法。我有一种感觉它可以在O(n^2)内完成,但任何更好的算法都需要创造性的数据结构。您需要能够更快地找到长度小于给定L的最重的杆,以达到更好的效果。