Задача о рюкзаке — различия между версиями
Строка 44: | Строка 44: | ||
'''Восстановим набор предметов, входящих в рюкзак''' | '''Восстановим набор предметов, входящих в рюкзак''' | ||
− | Будем определять входит ли <tex>n_i</tex> предмет с | + | Будем определять входит ли <tex>n_i</tex> предмет в искомый набор. Начинаем с элемента <tex>A(i,w)</tex>, где <tex>i = N</tex>, <tex>w = W</tex>. Для этого сравниваем <tex>A(i,w)</tex> со следующими значениями: |
#Максимальная стоимость рюкзака с такой же вместимостью и набором допустимых предметов <tex>\{n_1,n_2,...,n_{i-1}\}</tex>, то есть <tex>A(i-1, w)</tex> | #Максимальная стоимость рюкзака с такой же вместимостью и набором допустимых предметов <tex>\{n_1,n_2,...,n_{i-1}\}</tex>, то есть <tex>A(i-1, w)</tex> | ||
− | #Максимальная стоимость рюкзака с вместимостью на w_i меньше и набором допустимых предметов <tex>\{n_1,n_2,...,n_{i-1}\}</tex> плюс стоимость <tex>p_i</tex>, то есть <tex>A(i-1, w-w_i)+p_i</tex> | + | #Максимальная стоимость рюкзака с вместимостью на <tex>w_i</tex> меньше и набором допустимых предметов <tex>\{n_1,n_2,...,n_{i-1}\}</tex> плюс стоимость <tex>p_i</tex>, то есть <tex>A(i-1, w-w_i)+p_i</tex> |
Заметим, что при построении <tex>A</tex> мы выбирали максимум из этих значений и записывали в <tex>A(i, w)</tex>. Тогда будем сравнивать <tex>A(i, w)</tex> c <tex>A(i-1, w)</tex>, если равны, тогда <tex>n_i</tex> не входит в искомый набор, иначе входит. | Заметим, что при построении <tex>A</tex> мы выбирали максимум из этих значений и записывали в <tex>A(i, w)</tex>. Тогда будем сравнивать <tex>A(i, w)</tex> c <tex>A(i-1, w)</tex>, если равны, тогда <tex>n_i</tex> не входит в искомый набор, иначе входит. | ||
Строка 59: | Строка 59: | ||
A[i][0] = 0 //Первые элементы приравниваем 0 | A[i][0] = 0 //Первые элементы приравниваем 0 | ||
for k = 1..N | for k = 1..N | ||
− | for s = 0..W //Перебираем для каждого | + | for s = 0..W //Перебираем для каждого k, все вместисмости |
if s >= w[k] //Если текущий предмет вмещается в рюкзак | if s >= w[k] //Если текущий предмет вмещается в рюкзак | ||
A[k][s] = max(A[k-1][s], A[k-1][s-w[k]]+p[k]) //выбираем класть его или нет | A[k][s] = max(A[k-1][s], A[k-1][s-w[k]]+p[k]) //выбираем класть его или нет |
Версия 14:53, 29 декабря 2012
Задача о рюкзаке — дано
предметов, предмет имеет массу и стоимость . Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины (вместимость рюкзака), а суммарная стоимость была максимальна.Содержание
Формулировка задачи
Дано
предметов, - вместимость рюкзака, — соответствующий ему набор положительных целых весов, — соответствующий ему набор положительных целых стоимостей. Нужно найти набор бинарных величин , где , если предмет включен в набор, , если предмет не включен, и такой что:- максимальна.
Варианты решения
Задачу о рюкзаке можно решить несколькими способами:
- Перебирать все подмножества набора из N предметов. Сложность такого решения .
- Методом Meet-in-the-middle. Сложность решения
- Метод динамического программирования. Сложность - .
Метод динамического программирования
Пусть
есть максимальная стоимости предметов, которые можно уложить в рюкзак вместимости , если можно использовать только первые предметов, то есть , назовем этот набор допустимых предметов для .
Найдем
. Возможны 2 варианта:- Если предмет не попал в рюкзак. Тогда равно максимальной стоимости рюкзака с такой же вместимостью и набором допустимых предметов , то есть
- Если попал в рюкзак. Тогда равно максимальной стоимости рюкзака, где вес уменьшаем на вес -ого предмета и набор допустимых предметов плюс стоимость , то есть
Если короче:
Выберем из этих двух значений максимальное:
Стоимость искомого набора равна
, так как нужно найти максимальную стоимость рюкзака, где все предметы допустимы и вместимость рюкзака .Восстановим набор предметов, входящих в рюкзак
Будем определять входит ли
предмет в искомый набор. Начинаем с элемента , где , . Для этого сравниваем со следующими значениями:- Максимальная стоимость рюкзака с такой же вместимостью и набором допустимых предметов , то есть
- Максимальная стоимость рюкзака с вместимостью на меньше и набором допустимых предметов плюс стоимость , то есть
Заметим, что при построении
мы выбирали максимум из этих значений и записывали в . Тогда будем сравнивать c , если равны, тогда не входит в искомый набор, иначе входит.Реализация
Сначала генерируем
.for i = 0..W A[0][i] = 0 for i = 0..N A[i][0] = 0 //Первые элементы приравниваем 0 for k = 1..N for s = 0..W //Перебираем для каждого k, все вместисмости if s >= w[k] //Если текущий предмет вмещается в рюкзак A[k][s] = max(A[k-1][s], A[k-1][s-w[k]]+p[k]) //выбираем класть его или нет else A[k][s] = A[k-1][s] //иначе, не кладем
Затем найдем набор
предметов, входящих в рюкзак, рекурсивной функцией:findAns(k, s) if A[k][s] == 0 return if A[k-1][s] == A[k][s] findAns(k-1, s) else findAns(k-1, s - w[k]); ans.push(k);
Сложность алгоритма
Пример
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | |
k = 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
k = 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
k = 2 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 7 | 7 | 7 | 7 | 7 |
k = 3 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 11 | 11 |
k = 4 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
k = 5 | 0 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
Числа от 0 до 13 в первой строчке обозначают вместимость рюкзака.
В первой строке как только вместимость рюкзака
, добавляем в рюкзак 1 предмет.Картинка
Рассмотрим
, при каждом так как сравниваем и и записываем в стоимость либо рюкзака без третьего предмета, но с таким же весом, либо с третьим предметом, тогда стоимость равна стоимоси третьего предмета плюс стоимость рюкзака с вместимостью на меньше.Максимальная стоимость рюкзака находится в
.Восстановление набора предметов, из которых состоит максимально дорогой рюкзак.
Начиная с
восстанавливаем ответ.Картинка
Таким образом, набор состоит из
предметов.Стоимость рюкзака
Вес рюкзака