我正在研究一个解决0/1背包问题变体的程序。
此处描述了原始问题:https://en.wikipedia.org/wiki/Knapsack_problem。
如果以后链接丢失,我会给你一个0/1背包问题的摘要(如果你熟悉它,跳过这一段):
假设我们有n
项,每项都有权重wi
和值vi
。我们希望将物品放入一个支撑最大重量W
的袋子中,这样袋子内的总值就可以达到最大值,而不会超过袋子。项目不能有多个实例(即,我们只有一个实例)。问题的目标是maximize SUM(vi.xi)
,以便SUM(wi.xi) <= W
和xi = 0, 1
(xi
代表商品中包含或不包含的商品的状态。)
就我而言,条件和目标都存在细微差别:
所有项目的权重为1,wi = 1, i = 1...n
我总是想把一半的物品放在包里。因此,行李的最大重量容量是物品数量的一半(四舍五入)。W = ceil[n/2]
或W = floor[(n+1)/2]
。
此外,包内的重量必须等于其最大容量SUM(wi.xi) = W
最后,不是最大化包内物品的价值,而是目标是内部物品的价值尽可能接近外面物品的价值。因此,我的目标是minimize |SUM(vi.-xi) - SUM[vi(1-xi)]|
,简化为minimize |SUM[vi(2xi - 1)]|
。
现在,上面的维基百科页面中有一个原始0/1背包问题的伪代码(你可以在本文的底部找到它),但我无法适应我的场景。有人可以帮忙吗? (我不是要求代码,只是为了一个想法,所以语言无关紧要)
谢谢!
维基百科的0/1背包问题的伪代码:
假设
w1, w2, ..., wn, W
是严格正整数。限定m[i,w]
是重量减去可以达到的最大值 使用最多w
项(i
个项目)的i
以上。我们可以递归地定义
m[i,w]
,如下所示:
m[0, w]=0
m[i, w] = m[i-1, w] if wi > w
(新项目超过当前的重量限制)m[i, w]= max(m[i-1, w], m[i-1, w-wi] + vi) if wi <= w
。然后可以通过计算
m[n,W]
找到解决方案。// Input: // Values (stored in array v) // Weights (stored in array w) // Number of distinct items (n) // Knapsack capacity (W) for j from 0 to W do: m[0, j] := 0 for i from 1 to n do: for j from 0 to W do: if w[i-1] <= j then: m[i, j] := max(m[i-1, j], m[i-1, j-w[i-1]] + v[i-1]) else: m[i, j] := m[i-1, j]
答案 0 :(得分:2)
感谢@harold,似乎这个问题不是背包问题,而是分区问题。我正在寻找的部分伪代码位于相应的维基百科页面中:https://en.wikipedia.org/wiki/Partition_problem
编辑:实际上,分区问题算法会告诉您一组项目是否可以分为两组相等的值。假设它不能,你有近似算法,它表示你是否可以将这些集合分成两组,差别是它们的值低于d
。
但是,他们并没有告诉你所产生的子集,而这正是我所寻求的。
我最终在这里找到了一个问题(这里:Balanced partition),并且我已经测试了一个代码示例并且工作正常。