多重背包/装箱算法
Posted
技术标签:
【中文标题】多重背包/装箱算法【英文标题】:Multiple Knapsack/Bin-packing algorithm 【发布时间】:2018-04-15 17:57:00 【问题描述】:问题如下:
你有一个包含 n 个对象的堆栈,每个对象的体积为 Vi。你也有 k 个盒子,它们都有一个固定的体积 V。对于堆栈顶部的每个对象,如果该对象适合当前的盒子,你必须在将它放入盒子和移动到下一个对象之间做出选择,或关闭此框并跳至下一个框。
每个盒子的成本定义为盒子里剩下的体积的平方。
您的目标是将所有对象放入盒子中,并最小化所有盒子成本的总和。
我应该使用什么算法(我在想一些图表)?
【问题讨论】:
查看en.wikipedia.org/wiki/Knapsack_problem#Solving @yalpsideman 不太可能有解决方案,因为这个问题是一个相当受限的版本:考虑对象的顺序是固定的。 【参考方案1】:这可以通过动态规划来解决。
状态可以是(满箱数,取走物数)。
函数是达到这种状态的最小总成本。
可以如下进行转换。
让我们从状态(box, obj)
开始,当我们已经知道实现它的最佳方法时,成本为f[box][obj]
。
取对象编号obj+1
、obj+2
、...
,直到它们的体积总和v[i]
超过盒子容量V
。
在获取每个新对象i
之后,如果我们关闭当前框会发生什么?
我们已经达到状态(box + 1, i)
,成本是f[box][obj]
加上(V减去体积之和v[obj+1]
、v[obj+2]
、...
、v[i]
)的平方。
如果这是迄今为止实现(box+1, i)
状态的最佳方式,请将其分配给f[box+1][i]
。
基地是f[0][0] = 0
。
答案是f[k][n]
,其中k
是盒子的数量,n
是对象的数量。
在伪代码中:
f = array [0..k] [0..n] of integers
fill f[][] with infinity
f[0][0] = 0
for box = 0, 1, ..., k-1:
for obj = 0, 1, ..., n:
if f[box][obj] < infinity:
left = V
f[box+1][obj] = min (f[box+1][obj], f[box][obj] + V*V)
for i = obj+1, obj+2, ..., n:
left -= v[i]
if left < 0:
break
f[box+1][i] = min (f[box+1][i], f[box][obj] + left*left)
answer = f[k][n]
【讨论】:
你的回答真的很好,但是我觉得我表达的问题不够好……我忘了说最后的成本也考虑了空箱。示例:第 5 卷的 2 个对象和第 10 卷的 2 个盒子,通过每个盒子分配一个对象,可能的最低成本是 50。你认为我们可以调整你的算法吗? 啊,对不起,我错过了盒子数量为固定整数的部分K
。那么答案就是f[K][n]
。我们必须添加一个对应于空框的转换,这是在内部i
循环之前添加的一行。我会在一两个小时内编辑代码。
@leodaher 编辑了答案以完全使用k
框。以上是关于多重背包/装箱算法的主要内容,如果未能解决你的问题,请参考以下文章