抛物线背包
假设我有一条抛物线。现在我还有一堆宽度相同的棍子(是的,我的绘画技巧太棒了!)。如何将这些木棍堆叠在抛物线内,以便尽可能减少其使用的空间?我相信这属于背包问题的类别,但这个维基百科页面似乎没有让我更接近现实世界的解决方案。这是一个 NP 难问题吗?
在这个问题中,我们试图最小化消耗的面积(例如:积分),其中包括垂直面积。
Lets say I have a parabola. Now I also have a bunch of sticks that are all of the same width (yes my drawing skills are amazing!). How can I stack these sticks within the parabola such that I am minimizing the space it uses as much as possible? I believe that this falls under the category of Knapsack problems, but this Wikipedia page doesn't appear to bring me closer to a real world solution. Is this a NP-Hard problem?
In this problem we are trying to minimize the amount of area consumed (eg: Integral), which includes vertical area.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我使用 processing.js 和 HTML5 canvas 在 JavaScript 中编写了一个解决方案。
如果您想创建自己的解决方案,该项目应该是一个很好的起点。我添加了两个算法。一种将输入块从最大到最小排序,另一种随机对列表进行洗牌。然后尝试将每个项目从底部(最小的桶)开始放入桶中,并向上移动,直到有足够的空间容纳。
根据输入的类型,排序算法可以在 O(n^2) 内给出良好的结果。这是排序输出的示例。
这是按顺序插入算法。
github 上的项目 - https://github.com/gradbot/Parabolic-Knapsack
这是一个公共仓库因此,请随意分支并添加其他算法。我将来可能会添加更多内容,因为这是一个有趣的问题。
I cooked up a solution in JavaScript using processing.js and HTML5 canvas.
This project should be a good starting point if you want to create your own solution. I added two algorithms. One that sorts the input blocks from largest to smallest and another that shuffles the list randomly. Each item is then attempted to be placed in the bucket starting from the bottom (smallest bucket) and moving up until it has enough space to fit.
Depending on the type of input the sort algorithm can give good results in O(n^2). Here's an example of the sorted output.
Here's the insert in order algorithm.
Project on github - https://github.com/gradbot/Parabolic-Knapsack
It's a public repo so feel free to branch and add other algorithms. I'll probably add more in the future as it's an interesting problem.
简化
首先我想简化问题,为此:
[a, b],其中 a = 0
,对于本例b = 3
假设您给出了
b
(间隔的第二部分)和w
(间隔的宽度)一个段),那么您可以通过n=Floor[b/w]
找到段的总数。在这种情况下,存在一个最大化黎曼和的简单情况,并且获得第 i 段高度的函数是:f(b-(b*i)/(n+1)))。实际上这是一个假设,我并不能100%确定。函数
Sqrt[x]
实值的闭区间[0, 3]
上17
段的最大示例:本例中的段 heights 函数为
Re[Sqrt[3-3*范围[1,17]/18]]
,值为:What you have archived is a Bin-Packing problem,带有部分填充的垃圾箱。
查找 b
如果
b
未知,或者我们的任务是在所有木棍形成初始束拟合的情况下找到尽可能小的b
。然后我们可以将至少b
值限制为:段数 = 棒数最长棒 < ;最长线段高度查找
b
的最简单方法之一是在(上限-下限)/2
处进行枢轴查找是否存在解。然后它变成新的上限或下限,您重复该过程直到满足所需的精度。当您寻找
b
时,您不需要精确的结果,但不是最优的,如果您使用有效的算法来找到与实际b
相对接近的枢轴点,速度会快得多。例如:
Simplifying
First I want to simplify the problem, to do that:
[a, b], where a = 0
and for this exampleb = 3
Lets say you are given
b
(second part of interval) andw
(width of a segment), then you can find total number of segments byn=Floor[b/w]
. In this case there exists a trivial case to maximize Riemann sum and function to get i'th segment height is:f(b-(b*i)/(n+1)))
. Actually it is an assumption and I'm not 100% sure.Max'ed example for
17
segments on closed interval[0, 3]
for functionSqrt[x]
real values:And the segment heights function in this case is
Re[Sqrt[3-3*Range[1,17]/18]]
, and values are:What you have archived is a Bin-Packing problem, with partially filled bin.
Finding b
If
b
is unknown or our task is to find smallest possibleb
under what all sticks form the initial bunch fit. Then we can limit at leastb
values to:number of segments = number of stickslongest stick < longest segment heightOne of the simplest way to find
b
is to take a pivot at(higher limit-lower limit)/2
find if solution exists. Then it becomes new higher or lower limit and you repeat the process until required precision is met.When you are looking for
b
you do not need exact result, but suboptimal and it would be much faster if you use efficient algorithm to find relatively close pivot point to actualb
.For example:
这相当于有多个背包(假设这些块具有相同的“高度”,这意味着每“行”有一个背包),因此是装箱问题的一个实例。
请参阅http://en.wikipedia.org/wiki/Bin_packing
This is equivalent to having multiple knapsacks (assuming these blocks are the same 'height', this means there's one knapsack for each 'line'), and is thus an instance of the bin packing problem.
See http://en.wikipedia.org/wiki/Bin_packing
就像处理任何其他装箱问题一样处理它。我会在其上添加元启发式算法(例如禁忌搜索、模拟退火……),因为这些算法不是问题具体的。
例如,如果我从我的云平衡问题(= Bin Packing 的一种形式)位于 Drools Planner 中。如果所有的棍子都具有相同的高度,并且彼此顶部的 2 根棍子之间没有垂直空间,则无需进行太多更改:
Computer
重命名为ParabolicRow
。删除它的属性(CPU、内存、带宽)。给它一个唯一的级别
(其中0是最低行)。创建多个ParabolicRows
。Process
重命名为Stick
ProcessAssignment
重命名为StickAssignment
ParabolicRow
的所有Sticks
。ParabolicRows
的最高级别
。Just deal with it like any other Bin Packing problem. I'd throw meta-heuristics on it (such as tabu search, simulated annealing, ...) since those algorithms aren't problem specific.
For example, if I'd start from my Cloud Balance problem (= a form of Bin Packing) in Drools Planner. If all the sticks have the same height and there's no vertical space between 2 sticks on top of each other, there's not much I'd have to change:
Computer
toParabolicRow
. Remove it's properties (cpu, memory, bandwith). Give it a uniquelevel
(where 0 is the lowest row). Create a number ofParabolicRows
.Process
toStick
ProcessAssignement
toStickAssignment
Sticks
assigned to aParabolicRow
.level
of allParabolicRows
.我非常确定它相当于装箱:
非正式减少
最宽行的宽度,使箱变大 2 倍,并为每一行创建一个占位符元素,其大小为 2 倍行宽度。因此两个占位符元素不能打包到一个 bin 中。
为了减少抛物线背包上的装箱,您只需为所有大于所需 binsize 且大小为 width-binsize 的行创建占位符元素。此外,为小于 binsize 的所有行添加占位符,以填充整行。
这显然意味着你的问题是 NP 难的。
对于其他想法,请查看这里:http://en.wikipedia.org/wiki/Cutting_stock_problem
I'm very sure it is equivalent to bin-packing:
informal reduction
Be x the width of the widest row, make the bins 2x big and create for every row a placeholder element which is 2x-rowWidth big. So two placeholder elements cannot be packed into one bin.
To reduce bin-packing on parabolic knapsack you just create placeholder elements for all rows that are bigger than the needed binsize with size width-binsize. Furthermore add placeholders for all rows that are smaller than binsize which fill the whole row.
This would obviously mean your problem is NP-hard.
For other ideas look here maybe: http://en.wikipedia.org/wiki/Cutting_stock_problem
这很可能是 1-0 背包问题或装箱问题。这是一个 NP 难题,很可能这个问题我不明白,我无法向你解释,但你可以用贪心算法进行优化。这是一篇关于它的有用文章 http://www.developerfusion.com/article/5540/ bin-packing,我用它来在 phpclasses.org 上对我的 php 类进行 bin-packing。
Most likely this is the 1-0 Knapsack or a bin-packing problem. This is a NP hard problem and most likely this problem I don't understand and I can't explain to you but you can optimize with greedy algorithms. Here is a useful article about it http://www.developerfusion.com/article/5540/bin-packing that I use to make my php class bin-packing at phpclasses.org.
向那些提到水平可以处于不同高度这一事实的人提供支持(例如:假设棍子有 1 个“粗”,水平 1 从 0.1 单位变为 1.1 单位,或者可以从 0.2 单位变为 1.2 单位)
您可以课程扩展“多箱包装”方法并测试任意小的增量。 (例如:运行级别从 0.0、0.1、0.2、... 0.9 开始的多重装箱方法),然后选择最佳结果,但除非您有某种方法,否则您似乎会陷入无限长的计算中验证你是否得到了“正确”的结果(或者更准确地说,你的所有“行”所包含的内容都是正确的,此时你可以将它们向下移动,直到它们遇到抛物线的边缘)
此外, OP 没有明确指出木棍必须水平放置 - 尽管OP 可能用那些可爱的图画暗示了这一点。
我不知道如何最佳地解决这样的问题,但我敢打赌,在某些情况下,您可以随机放置木棍,然后测试它们是否在抛物线“内部”,并且它会击败任何仅依赖于水平的方法行。
(考虑一下我们试图用一根长棍子填充一条狭窄抛物线的情况。)
我说只需将它们全部扔在那里并摇动它们即可;)
Props to those who mentioned the fact that the levels could be at varying heights (ex: assuming the sticks are 1 'thick' level 1 goes from 0.1 unit to 1.1 units, or it could go from 0.2 to 1.2 units instead)
You could of course expand the "multiple bin packing" methodology and test arbitrarily small increments. (Ex: run the multiple binpacking methodology with levels starting at 0.0, 0.1, 0.2, ... 0.9) and then choose the best result, but it seems like you would get stuck calulating for an infinite amount of time unless you had some methodlogy to verify that you had gotten it 'right' (or more precisely, that you had all the 'rows' correct as to what they contained, at which point you could shift them down until they met the edge of the parabola)
Also, the OP did not specify that the sticks had to be laid horizontally - although perhaps the OP implied it with those sweet drawings.
I have no idea how to optimally solve such an issue, but i bet there are certain cases where you could randomly place sticks and then test if they are 'inside' the parabola, and it would beat out any of the methodologies relying only on horizontal rows.
(Consider the case of a narrow parabola that we are trying to fill with 1 long stick.)
I say just throw them all in there and shake them ;)