這是我以前的question的後續。我仍然發現它非常有趣的問題,因爲有一種算法值得更多的關注,我在這裏發佈它。Pisinger的子集求和算法的快速解決方案
從Wikipedia:對於每個xi都是正數並且以相同常數爲界的情況,Pisinger找到了線性時間算法。
還有一篇文章似乎描述了相同的算法,但有點難以閱讀,所以請 - 有誰知道如何將僞代碼從第4頁(balsub
)轉換爲工作實現?
這裏有兩個指針我收集迄今:
http://www.diku.dk/~pisinger/95-6.ps(紙)
https://stackoverflow.com/a/9952759/1037407
http://www.diku.dk/hjemmesider/ansatte/pisinger/codes.html
PS:我真的不堅持正是這個算法,如果你知道的任何其他類似的表演算法,請隨時建議它下面。
編輯
這是代碼的Python版本通過oldboy波紋管發佈:
class view(object):
def __init__(self, sequence, start):
self.sequence, self.start = sequence, start
def __getitem__(self, index):
return self.sequence[index + self.start]
def __setitem__(self, index, value):
self.sequence[index + self.start] = value
def balsub(w, c):
'''A balanced algorithm for Subset-sum problem by David Pisinger
w = weights, c = capacity of the knapsack'''
n = len(w)
assert n > 0
sum_w = 0
r = 0
for wj in w:
assert wj > 0
sum_w += wj
assert wj <= c
r = max(r, wj)
assert sum_w > c
b = 0
w_bar = 0
while w_bar + w[b] <= c:
w_bar += w[b]
b += 1
s = [[0] * 2 * r for i in range(n - b + 1)]
s_b_1 = view(s[0], r - 1)
for mu in range(-r + 1, 1):
s_b_1[mu] = -1
for mu in range(1, r + 1):
s_b_1[mu] = 0
s_b_1[w_bar - c] = b
for t in range(b, n):
s_t_1 = view(s[t - b], r - 1)
s_t = view(s[t - b + 1], r - 1)
for mu in range(-r + 1, r + 1):
s_t[mu] = s_t_1[mu]
for mu in range(-r + 1, 1):
mu_prime = mu + w[t]
s_t[mu_prime] = max(s_t[mu_prime], s_t_1[mu])
for mu in range(w[t], 0, -1):
for j in range(s_t[mu] - 1, s_t_1[mu] - 1, -1):
mu_prime = mu - w[j]
s_t[mu_prime] = max(s_t[mu_prime], j)
solved = False
z = 0
s_n_1 = view(s[n - b], r - 1)
while z >= -r + 1:
if s_n_1[z] >= 0:
solved = True
break
z -= 1
if solved:
print c + z
print n
x = [False] * n
for j in range(0, b):
x[j] = True
for t in range(n - 1, b - 1, -1):
s_t = view(s[t - b + 1], r - 1)
s_t_1 = view(s[t - b], r - 1)
while True:
j = s_t[z]
assert j >= 0
z_unprime = z + w[j]
if z_unprime > r or j >= s_t[z_unprime]:
break
z = z_unprime
x[j] = False
z_unprime = z - w[t]
if z_unprime >= -r + 1 and s_t_1[z_unprime] >= s_t[z]:
z = z_unprime
x[t] = True
for j in range(n):
print x[j], w[j]
那麼....我能說什麼。這和原作者寫的一樣好。我真的非常感謝,這是一段很棒的代碼。最後一個問題:是否有可能歸還所有有助於最終金額的項目? – 2012-04-03 20:50:28
完成,但沒有很好地測試。謹慎行事。 – oldboy 2012-04-03 22:52:50
+1。 _非常好。由於我們最初是在Python中拋出這個問題的,因此我正在考慮放棄包含解決方案的更新版本,而不僅僅是'balsub'。 – MrGomez 2012-04-04 06:58:49