Почему, когда традиционно рассказывают про рюкзак (однопараметровый, где у предметов есть только вес: N предметов с весами wi и max размер рюкзака S), то используют двумерный массив состояний, где dp[i][j] = bool, который означает, можно ли набрать вес j используя или не используя i-й предмет. Но ведь это решение тратит N * S памяти, можно же сделать то же самое с одномерным массивом dp[i] = true, проходя по всем true и дорисовывая ребра из i-го веса (если там true) в dp[i + wj] = true. По времени тоже N * S, но по памяти просто S
Вы не правы. Двумерный массив считает, можно ли набрать вес i используя первые j предметов. А не j-ый предмет.
Далее, обычно можно сэкономить память храня и пересчитывая только одну строку этого массива, но ДП все еще остается двумерным. Также числа Фибоначчи можно считать храня лишь 2 последних числа, но на самом деле там массив на n элементов в дп.
Этот трюк не всегда возможен. Например, если вам надо не только максимальный вес/цену найти, а еще и набор предметов. Восстановление ответа не всегда можно сделать лишь по последней строке.
для одномерного массива вроде всё ок восстанавливается
d[i] = bool хранится, можно ли получить вес = i
ну и для восстановления ответа, находясь на j-м предмете, в позиции i проверяем, есть ли ребро (dp[i - item[j].weight] == true) используя j-й предмет, если есть то добавляем в ответ, и идём к j-1 предмету
floppa322, Зависит от задачи. Если у вас можно предметы использовать только по одному разу, то нельзя из только последней строки восстановить ответ. В некоторых задачах, как рюкзак без цен с повторениями, действительно, трюк с сокращением таблицы ДП не имеет недостатков.
floppa322, Зависит от задачи. Если у вас можно предметы использовать только по одному разу, то нельзя из только последней строки восстановить ответ
хм, а если в таком случае для i-го веса перебирать все N предметов ? тогда правда в отличие от 2-D динамики сложность восстановления ответа будет не S, а N * S
хм, а если в таком случае для i-го веса перебирать все N предметов ?
Не поможет. Проблема в том, что вы не знаете, какие из предметов можно брать для текущего i-ого веса - вдруг они вам очень нужны в конце будут. И просто по одной последней строке вы никак это не определите вообще. И в итоге ваше восстановление ответа может взять один предмет несколько раз, или, если этого избегать, прийти в тупик: все возможные предметы для i-ого веса уже взяты в ответ и что делать вообще непонятно.
Иногда можно прям в массиве хранить множество всех предметов, Но это уже не O(S) памяти. Возможно, это все равно меньше O(SN) для полной матрицы, но не факт.