Задача о рюкзаке — различия между версиями
Margarita (обсуждение | вклад) |
Margarita (обсуждение | вклад) |
||
Строка 18: | Строка 18: | ||
3. Метод динамического программирование. Сложность - <tex>O(k \times W)</tex>. Рассмотрим этот алгоритм подробнее. | 3. Метод динамического программирование. Сложность - <tex>O(k \times W)</tex>. Рассмотрим этот алгоритм подробнее. | ||
+ | |||
+ | '''Алгоритм <tex>O(k \times W)</tex>''' | ||
Пусть <tex>A(s, n)</tex> есть максимальная стоимости предметов, которые можно уложить в рюкзак вместимости n, если можно использовать только первые s предметов из заданных k. | Пусть <tex>A(s, n)</tex> есть максимальная стоимости предметов, которые можно уложить в рюкзак вместимости n, если можно использовать только первые s предметов из заданных k. | ||
Строка 43: | Строка 45: | ||
Сначала генерируем <tex>А</tex> | Сначала генерируем <tex>А</tex> | ||
− | for (i = 0; i <= W; ++i) | + | for (i = 0; i <= W; ++i) |
A[0][i] = 0 | A[0][i] = 0 | ||
− | for (i = 0; i <= k; ++i) | + | for (i = 0; i <= k; ++i) |
A[i][0] = 0 {Первые элементы приравниваем 0} | A[i][0] = 0 {Первые элементы приравниваем 0} | ||
− | for (s = 1; s <= k; ++s) | + | for (s = 1; s <= k; ++s) |
− | for (n = 0; n <= W; ++n) | + | for (n = 0; n <= W; ++n) {Перебираем для каждого s, все n} |
if n >= w[s] {Если текущий предмет можно положить в рюкзак} | 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] {иначе, не кладем} | ||
Затем найдем набор <tex>ans</tex> предметов, входящих в рюкзак, рекурсивной функцией: | Затем найдем набор <tex>ans</tex> предметов, входящих в рюкзак, рекурсивной функцией: | ||
− | void findAns( | + | void findAns(s, n) |
if A[s][n] == 0 | if A[s][n] == 0 | ||
− | + | return | |
if A[s-1][n] == A[s][n] | if A[s-1][n] == A[s][n] | ||
− | + | findAns(s-1, n) | |
− | + | else | |
− | + | findAns(s-1, n - w[s]); | |
− | + | ans.push(s); | |
== Пример == | == Пример == |
Версия 19:58, 18 декабря 2012
Задача о рюкзаке — дано
предметов, i-й предмет имеет массу и стоимость . Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины (вместимость рюкзака), а суммарная стоимость была максимальна.Формулировка задачи
Дано
предметов, - вместимость рюкзака, — соответствующий ему набор положительных целых весов, — соответствующий ему набор положительных целых стоимостей. Нужно определить набор бинарных величин , где , если предмет включен в набор, , если предмет не включен, такой что:1.
2.
максимальна.Алгоритм
Задачу о рюкзаке можно решить несколькими способами:
1. Перебирая все подмножества набора из k предметов. Сложность такого решения
.2. Методом Meet-in-the-middle. Сложность решения
3. Метод динамического программирование. Сложность -
. Рассмотрим этот алгоритм подробнее.Алгоритм
Пусть
есть максимальная стоимости предметов, которые можно уложить в рюкзак вместимости n, если можно использовать только первые s предметов из заданных k.
Найдем
. Возможны 2 варианта:1. Если предмет
не попал в рюкзак. Тогда2. Если
попал в рюкзак. ТогдаТаким образом:
Теперь найдем набор предметов, входящих в рюкзак.
Рассмотрим входит ли
- последний предмет в рюкзак. Если равно , значит последний предмет не входит в набор, иначе входит. Так рекусривно идем до первого предмета. Получаем искомый набор.Сложность алгоритма
Реализация
Сначала генерируем
for (i = 0; i <= W; ++i) A[0][i] = 0 for (i = 0; i <= k; ++i) A[i][0] = 0 {Первые элементы приравниваем 0} for (s = 1; s <= k; ++s) for (n = 0; n <= W; ++n) {Перебираем для каждого 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] {иначе, не кладем}
Затем найдем набор
предметов, входящих в рюкзак, рекурсивной функцией:void 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);
Пример
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
s = 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
s = 1 | 0 | 0 | 0 | 0 | 0 | 0 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 |
s = 2 | 0 | 0 | 0 | 0 | 3 | 3 | 5 | 5 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 |
s = 3 | 0 | 0 | 0 | 1 | 3 | 3 | 5 | 5 | 5 | 6 | 8 | 8 | 8 | 9 | 9 | 9 |
s = 4 | 0 | 0 | 3 | 3 | 3 | 4 | 6 | 6 | 8 | 8 | 8 | 9 | 11 | 11 | 11 | 12 |
s = 5 | 0 | 0 | 3 | 3 | 3 | 6 | 6 | 9 | 9 | 9 | 10 | 12 | 12 | 14 | 14 | 14 |
Числа от 0 до 15 в первой строчке обозначают вместимость рюкзака.
Рассмотрим стоку
. То есть можно использовать только первый предмет, у которого.
при ,
при , так как
Рассмотрим строку
. То есть можно использовать первые 2 предмета.
, при , так как нельзя положить в рюкзак предмет.
, при остальных . А именно:
Максимальная стоимость рюкзака находится в
.Теперь восстановим набор предметов, из которых состоит максимально дорогой рюкзак.
Сравниваем
и . Не равны. Следовательно, предмет входит в искомый набор, переходим к предмету с весом рюкзака . То естьСравниваем
и . Равны. Следовательно, предмет не входит в набор, переходим к предмету с тем же весом рюкзака.Сравниваем
и . Равны. Следовательно, предмет не входит в набор, переходим к предмету с тем же весом рюкзака.Сравниваем
и . Не равны. Следовательно, предмет входит в набор, уменьшаем вес рюкзака на , переходим к предмету.Сравниваем
и . Не равны. Следовательно, предмет входит в набор.Таким образом, набор состоит из
предметов.Стоимость рюкзака
Вес рюкзака