Задача о рюкзаке — различия между версиями
Margarita (обсуждение | вклад) |
Margarita (обсуждение | вклад) |
||
| Строка 69: | Строка 69: | ||
== Пример == | == Пример == | ||
| − | <tex>W = | + | <tex>W = 13, k = 5</tex> |
| − | <tex>w_{1} = | + | <tex>w_{1} = 3, p_{1} = 1 </tex> |
| − | <tex>w_{2} = 4, p_{2} = | + | <tex>w_{2} = 4, p_{2} = 6 </tex> |
| − | <tex>w_{3} = | + | <tex>w_{3} = 5, p_{3} = 4 </tex> |
| − | <tex>w_{4} = | + | <tex>w_{4} = 8, p_{4} = 7 </tex> |
| − | <tex>w_{5} = | + | <tex>w_{5} = 9, p_{5} = 6 </tex> |
{| class="wikitable" cellpadding="4" border="1" style="border-collapse: collapse;" | {| class="wikitable" cellpadding="4" border="1" style="border-collapse: collapse;" | ||
|- | |- | ||
| − | | || 0|| | + | | s = 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0 |
|- | |- | ||
| − | | s = | + | | s = 1|| 0|| 0|| 0|| 1|| 1|| 1|| 1|| 1|| 1|| 1|| 1|| 1|| 1|| 1 |
|- | |- | ||
| − | | s = | + | | s = 2|| 0|| 0|| 0|| 1|| 6|| 6|| 6|| 7|| 7|| 7|| 7|| 7|| 7|| 7 |
|- | |- | ||
| − | | s = | + | | s = 3|| 0|| 0|| 0|| 1|| 6|| 6|| 6|| 7|| 7|| 10|| 10|| 10|| 11|| 11 |
|- | |- | ||
| − | | s = | + | | s = 4|| 0|| 0|| 0|| 1|| 6|| 6|| 6|| 7|| 7|| 10|| 10|| 10|| 13|| 13 |
|- | |- | ||
| − | | s = | + | | s = 5|| 0|| 0|| 0|| 1|| 6|| 6|| 6|| 7|| 7|| 10|| 10|| 10|| 13|| 13 |
| − | |||
| − | |||
|} | |} | ||
Числа от 0 до 15 в первой строчке обозначают вместимость рюкзака. | Числа от 0 до 15 в первой строчке обозначают вместимость рюкзака. | ||
| − | + | В первой строке как только вместимость рюкзака <tex>n /ge 3</tex>, добавляем в рюкзак 1 предмет. | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | <tex> | + | Во второй строке, когда можно использовать первые <tex>2</tex> предмета. |
| − | |||
| − | |||
Максимальная стоимость рюкзака находится в <tex>A(5, 15)</tex>. | Максимальная стоимость рюкзака находится в <tex>A(5, 15)</tex>. | ||
Версия 10:54, 22 декабря 2012
Задача о рюкзаке — дано предметов, i-й предмет имеет массу и стоимость . Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины (вместимость рюкзака), а суммарная стоимость была максимальна.
Содержание
Формулировка задачи
Дано предметов, - вместимость рюкзака, — соответствующий ему набор положительных целых весов, — соответствующий ему набор положительных целых стоимостей. Нужно определить набор бинарных величин , где , если предмет включен в набор, , если предмет не включен, такой что:
1.
2. максимальна.
Варианты решения
Задачу о рюкзаке можно решить несколькими способами:
1. Перебирая все подмножества набора из k предметов. Сложность такого решения .
2. Методом Meet-in-the-middle. Сложность решения
3. Метод динамического программирование. Сложность - . Рассмотрим этот алгоритм подробнее.
Алгоритм
Пусть есть максимальная стоимости предметов, которые можно уложить в рюкзак вместимости n, если можно использовать только первые s предметов из заданных k.
Найдем . Возможны 2 варианта:
1. Если предмет не попал в рюкзак. Тогда
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] {иначе, не кладем}
Затем найдем набор предметов, входящих в рюкзак, рекурсивной функцией:
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);
Пример
| 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 предмет.
Во второй строке, когда можно использовать первые предмета.
Максимальная стоимость рюкзака находится в .
Теперь восстановим набор предметов, из которых состоит максимально дорогой рюкзак.
Сравниваем и . Не равны. Следовательно, предмет входит в искомый набор, переходим к предмету с весом рюкзака . То есть
Сравниваем и . Равны. Следовательно, предмет не входит в набор, переходим к предмету с тем же весом рюкзака.
Сравниваем и . Равны. Следовательно, предмет не входит в набор, переходим к предмету с тем же весом рюкзака.
Сравниваем и . Не равны. Следовательно, предмет входит в набор, уменьшаем вес рюкзака на , переходим к предмету.
Сравниваем и . Не равны. Следовательно, предмет входит в набор.
Таким образом, набор состоит из предметов.
Стоимость рюкзака
Вес рюкзака