Хитрость заключается в том, чтобы хранить дополнительную информацию, которая позволит вам восстановить выбор, сделанный на каждом шаге, при заполнении таблицы динамического программирования. Иногда сама таблица содержит такую информацию. Например, в задаче о ранце 0/1 вы можете узнать, какие предметы используются для достижения оптимального решения (обратите внимание, что нужна только таблица):
# 0/1 knapsack. O(nC) time, O(nC) space,
# also returns the index of the items to pick
# V: values, W: weights, C: capacity
def integral_knapsack_items(V, W, C):
table = integral_knapsack_table(V, W, C)
i, j, items = len(W), C, []
while i != 0 and j != 0:
if table[i][j] != table[i-1][j]:
items.append(i-1)
i, j = i-1, j-W[i-1]
else:
i -= 1
return (table[-1][-1], items)
def integral_knapsack_table(V, W, C):
m, n = len(W)+1, C+1
table = [[0] * n for x in xrange(m)]
for i in xrange(1, m):
for j in xrange(1, n):
if W[i-1] > j:
table[i][j] = table[i-1][j]
else:
table[i][j] = max(table[i-1][j],
V[i-1] + table[i-1][j-W[i-1]])
return table
В приведенном выше коде вы вызываете integral_knapsack_items()
с V
(массив значений), W
(массив соответствующих весов) и C
(емкость рюкзака), и процедура возвращает кортеж с максимальным значением, полученным при заполнении рюкзака, и индексами предметов, используемых для достижения этого значения.