Задача о рюкзаке
Версия от 12:58, 27 декабря 2012; Margarita (обсуждение | вклад)
Задача о рюкзаке — дано
предметов, предмет имеет массу и стоимость . Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины (вместимость рюкзака), а суммарная стоимость была максимальна.Содержание
Формулировка задачи
Дано
предметов, - вместимость рюкзака, — соответствующий ему набор положительных целых весов, — соответствующий ему набор положительных целых стоимостей. Нужно определить набор бинарных величин , где , если предмет включен в набор, , если предмет не включен, такой что:- максимальна.
Варианты решения
Задачу о рюкзаке можно решить несколькими способами:
- Перебирая все подмножества набора из k предметов. Сложность такого решения .
- Методом Meet-in-the-middleMeet-in-the-middle. Сложность решения
- Метод динамического программирование. Сложность - . Рассмотрим этот алгоритм подробнее.
Алгоритм
Пусть
есть максимальная стоимости предметов, которые можно уложить в рюкзак вместимости n, если можно использовать только первые s предметов из заданных k.
Найдем
. Возможны 2 варианта:- Если предмет не попал в рюкзак. Тогда
- Если попал в рюкзак. Тогда
Таким образом:
Теперь найдем набор предметов, входящих в рюкзак.
Рассмотрим входит ли
- последний предмет в рюкзак. Если равно , значит последний предмет не входит в набор, иначе входит. Так рекусривно идем до первого предмета. Получаем искомый набор.Реализация
Сначала генерируем
for i = 0..W A[0][i] = 0 for i = 0..k A[i][0] = 0 //Первые элементы приравниваем 0 for s = 1..k for n = 0..W //Перебираем для каждого s, все n if n >= w[s] //Если текущий предмет можно положить в рюкзак A[s][n] = max(A[s-1][n], A[s-1][n-w[s]]+p[s]) //выбираем класть его или нет else A[s][n] = A[s-1][n] //иначе, не кладем
Затем найдем набор
предметов, входящих в рюкзак, рекурсивной функцией:findAns(s, n) if A[s][n] == 0 return if A[s-1][n] == A[s][n] findAns(s-1, n) else findAns(s-1, n - w[s]); ans.push(s);
Сложность алгоритма
Пример
s = 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
s = 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
s = 2 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 7 | 7 | 7 | 7 | 7 |
s = 3 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 11 | 11 |
s = 4 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
s = 5 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
Числа от 0 до 15 в первой строчке обозначают вместимость рюкзака.
В первой строке как только вместимость рюкзака
, добавляем в рюкзак 1 предмет.Во второй строке, когда можно использовать первые
предмета.
Максимальная стоимость рюкзака находится в
.Теперь восстановим набор предметов, из которых состоит максимально дорогой рюкзак.
Сравниваем
и . Не равны. Следовательно, предмет входит в искомый набор, переходим к предмету с весом рюкзака . То естьСравниваем
и . Равны. Следовательно, предмет не входит в набор, переходим к предмету с тем же весом рюкзака.Сравниваем
и . Равны. Следовательно, предмет не входит в набор, переходим к предмету с тем же весом рюкзака.Сравниваем
и . Не равны. Следовательно, предмет входит в набор, уменьшаем вес рюкзака на , переходим к предмету.Сравниваем
и . Не равны. Следовательно, предмет входит в набор.Таким образом, набор состоит из
предметов.Стоимость рюкзака
Вес рюкзака