Đây là phần tiếp theo cho số question trước đó của tôi. Tôi vẫn tìm thấy nó rất thú vị vấn đề và như có một thuật toán mà đáng chú ý hơn tôi đang đăng nó ở đây.Giải pháp nhanh cho thuật toán Tổng số phụ của Pisinger
Từ Wikipedia: Đối với trường hợp mỗi xi là dương và bị giới hạn bởi cùng một hằng số, Pisinger tìm thấy thuật toán thời gian tuyến tính.
Có một loại giấy khác có vẻ như mô tả cùng một thuật toán nhưng có một chút khó đọc cho tôi - vậy có ai biết cách dịch mã giả từ trang 4 (balsub
) sang triển khai không?
Dưới đây là vài gợi ý tôi thu thập được cho đến nay:
http://www.diku.dk/~pisinger/95-6.ps (giấy)
https://stackoverflow.com/a/9952759/1037407
http://www.diku.dk/hjemmesider/ansatte/pisinger/codes.html
PS: Tôi không thực sự nhấn mạnh vào chính xác thuật toán này vì vậy nếu bạn biết bất kỳ thuật toán thực hiện tương tự nào khác, vui lòng đề xuất thuật toán dưới đây.
Sửa
Đây là một phiên bản Python của mã đăng tải dưới đây bởi 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]
Vâng .... tôi có thể nói gì. Điều này là tốt như thể nó được viết bởi tác giả gốc. Tôi thực sự, thật sự biết ơn, đó là một đoạn mã tuyệt vời. Một câu hỏi cuối cùng: là nó cũng có thể trả lại tất cả các vật phẩm góp phần vào tổng số cuối cùng? –
Xong, nhưng không được kiểm tra kỹ. Tiến hành thận trọng. – oldboy
+1. _Rất đẹp. Vì chúng tôi ban đầu đã ném điều này xung quanh trong Python, tôi đang xem xét thả một phiên bản cập nhật bao gồm các giải pháp thay vì chỉ 'balsub'. – MrGomez