Задача о рюкзаке — различия между версиями
Skipor (обсуждение | вклад) м (Раздел с другими задачами) |
Skipor (обсуждение | вклад) (→Другие задачи семейства: создание базовой структуры, первый тип) |
||
Строка 131: | Строка 131: | ||
=Другие задачи семейства= | =Другие задачи семейства= | ||
− | ==Ограниченый рюкзак (Bounded Knapsack Problem)== | + | ==Ограниченый рюкзак == |
− | ==Не | + | '''Ограниченый рюкзак''' (англ. ''Bounded Knapsack Problem'') - обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз. |
− | ==Непрерывный рюкзак (Continuous knapsack problem)== | + | ===Формулировка Задачи=== |
+ | Каждый предмет может быть выбран ограниченное <tex>b_i</tex> число раз. | ||
+ | Задача выбрать число <tex>x_i</tex> предметов каждого типа так, чтобы | ||
+ | |||
+ | максимизировать общую стоимость: <math>\sum_{i=1}^N p_ix_i</math> | ||
+ | |||
+ | выполнялось условие на совместность: <math>\sum_{i=1}^N w_ix_i \le W</math> | ||
+ | |||
+ | и <math> x_i \in (0,1,...,b_i)</math> для всех <math> i= 1,2,...,N</math> | ||
+ | |||
+ | ===Варианты решения=== | ||
+ | При небольших <tex>b_i</tex> решается сведением к классической задаче о рюкзаке. В иных случаях: | ||
+ | * Методом ветвей и границ | ||
+ | * Методом динамического программирования | ||
+ | |||
+ | ===Метод динамического программирования=== | ||
+ | Пусть <tex>d(i,c)</tex> максимальная стоимость любого возможного числа вещей типов от 1 до <tex>i</tex>, суммарным весом до <tex>c</tex>. | ||
+ | |||
+ | Заполним <tex>d(0,c)</tex> нулями. | ||
+ | |||
+ | Тогда меняя i от 1 до <tex>N</tex>, расчитаем на каждом шаге <tex>c</tex> от 0 до <tex>W</tex> по рекурентной формуле: | ||
+ | |||
+ | <tex>d(i,c) = max(d(i - 1, c - lw_i) + lp_i : l\ integer</tex> <math>0 \le l \le min(b_i,\lfloor c/w_i \rfloor))</math> | ||
+ | |||
+ | Если не нужно востанавливать ответ, то можно использовать одномерный массив <tex>d(c)</tex> вместо двумерного. | ||
+ | |||
+ | Сложность алгоритма <tex>O(NW^2)</tex>. | ||
+ | |||
+ | |||
+ | ==Не ограниченный рюкзак== | ||
+ | '''Не ограниченный рюкзак'''' (англ. "Unbounded Knapsack Problem") - обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз. | ||
+ | ===Формулировка Задачи=== | ||
+ | Каждый предмет может быть выбран ограниченное <tex>b_i</tex> число раз. | ||
+ | Задача выбрать число <tex>x_i</tex> предметов каждого типа так, чтобы | ||
+ | |||
+ | максимизировать общую стоимость: <math>\sum_{i=1}^N p_ix_i</math> | ||
+ | |||
+ | выполнялось условие на совместность: <math>\sum_{i=1}^N w_ix_i \le W</math> | ||
+ | |||
+ | и <math> x_i \in (0,1,...,b_i)</math> для всех <math> i= 1,2,...,N</math> | ||
+ | |||
+ | ===Варианты решения=== | ||
+ | При небольших <tex>b_i</tex> решается сведением к классической задаче о рюкзаке. В иных случаях: | ||
+ | * Методом ветвей и границ | ||
+ | * Методом динамического программирования | ||
+ | |||
+ | ===Метод динамического программирования=== | ||
+ | Пусть <tex>d(i,c)</tex> максимальная стоимость любого возможного числа вещей типов от 1 до <tex>i</tex>, суммарным весом до <tex>c</tex>. | ||
+ | |||
+ | Заполним <tex>d(0,c)</tex> нулями. | ||
+ | |||
+ | Тогда меняя i от 1 до <tex>N</tex>, расчитаем на каждом шаге <tex>c</tex> от 0 до <tex>W</tex> по рекурентной формуле: | ||
+ | |||
+ | <tex>d(i,c) = max(d(i - 1, c - lw_i) + lp_i : l\ integer</tex> <math>0 \le l \le min(b_i,\lfloor c/w_i \rfloor))</math> | ||
+ | |||
+ | Если не нужно востанавливать ответ, то можно использовать одномерный массив <tex>d(c)</tex> вместо двумерного. | ||
+ | |||
+ | Сложность алгоритма <tex>O(NW^2)</tex>. | ||
+ | |||
+ | ==Непрерывный рюкзак== | ||
+ | ""Непрерывный рюкзак"" (англ. "Continuous knapsack problem") -обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз. | ||
+ | ===Формулировка Задачи=== | ||
+ | Каждый предмет может быть выбран ограниченное <tex>b_i</tex> число раз. | ||
+ | Задача выбрать число <tex>x_i</tex> предметов каждого типа так, чтобы | ||
+ | |||
+ | максимизировать общую стоимость: <math>\sum_{i=1}^N p_ix_i</math> | ||
+ | |||
+ | выполнялось условие на совместность: <math>\sum_{i=1}^N w_ix_i \le W</math> | ||
+ | |||
+ | и <math> x_i \in (0,1,...,b_i)</math> для всех <math> i= 1,2,...,N</math> | ||
+ | |||
+ | ===Варианты решения=== | ||
+ | При небольших <tex>b_i</tex> решается сведением к классической задаче о рюкзаке. В иных случаях: | ||
+ | * Методом ветвей и границ | ||
+ | * Методом динамического программирования | ||
+ | |||
+ | ===Метод динамического программирования=== | ||
+ | Пусть <tex>d(i,c)</tex> максимальная стоимость любого возможного числа вещей типов от 1 до <tex>i</tex>, суммарным весом до <tex>c</tex>. | ||
+ | |||
+ | Заполним <tex>d(0,c)</tex> нулями. | ||
+ | |||
+ | Тогда меняя i от 1 до <tex>N</tex>, расчитаем на каждом шаге <tex>c</tex> от 0 до <tex>W</tex> по рекурентной формуле: | ||
+ | |||
+ | <tex>d(i,c) = max(d(i - 1, c - lw_i) + lp_i : l\ integer</tex> <math>0 \le l \le min(b_i,\lfloor c/w_i \rfloor))</math> | ||
+ | |||
+ | Если не нужно востанавливать ответ, то можно использовать одномерный массив <tex>d(c)</tex> вместо двумерного. | ||
+ | |||
+ | Сложность алгоритма <tex>O(NW^2)</tex>. | ||
= Литература = | = Литература = |
Версия 12:12, 11 января 2013
Задача о рюкзаке(англ. Knapsack problem) — дано
предметов, предмет имеет массу и стоимость . Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины (вместимость рюкзака), а суммарная стоимость была максимальна.Содержание
Формулировка задачи
Дано
предметов, - вместимость рюкзака, — соответствующий ему набор положительных целых весов, — соответствующий ему набор положительных целых стоимостей. Нужно найти набор бинарных величин , где , если предмет включен в набор, , если предмет не включен, и такой что:- максимальна.
Варианты решения
Задачу о рюкзаке можно решить несколькими способами:
- Перебирать все подмножества набора из 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 предмет.Рассмотрим
, при каждом так как сравниваем и и записываем в стоимость либо рюкзака без третьего предмета, но с таким же весом, либо с третьим предметом, тогда стоимость равна стоимоси третьего предмета плюс стоимость рюкзака с вместимостью на меньше.Максимальная стоимость рюкзака находится в
.Восстановление набора предметов, из которых состоит максимально дорогой рюкзак.
Начиная с
восстанавливаем ответ.Таким образом, в набор входит
и предмет.Стоимость рюкзака
Вес рюкзака
Другие задачи семейства
Ограниченый рюкзак
Ограниченый рюкзак (англ. Bounded Knapsack Problem) - обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз.
Формулировка Задачи
Каждый предмет может быть выбран ограниченное
число раз. Задача выбрать число предметов каждого типа так, чтобымаксимизировать общую стоимость:
выполнялось условие на совместность:
и
для всехВарианты решения
При небольших
решается сведением к классической задаче о рюкзаке. В иных случаях:- Методом ветвей и границ
- Методом динамического программирования
Метод динамического программирования
Пусть
максимальная стоимость любого возможного числа вещей типов от 1 до , суммарным весом до .Заполним
нулями.Тогда меняя i от 1 до
, расчитаем на каждом шаге от 0 до по рекурентной формуле:
Если не нужно востанавливать ответ, то можно использовать одномерный массив
вместо двумерного.Сложность алгоритма
.
Не ограниченный рюкзак
Не ограниченный рюкзак' (англ. "Unbounded Knapsack Problem") - обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз.
Формулировка Задачи
Каждый предмет может быть выбран ограниченное
число раз. Задача выбрать число предметов каждого типа так, чтобымаксимизировать общую стоимость:
выполнялось условие на совместность:
и
для всехВарианты решения
При небольших
решается сведением к классической задаче о рюкзаке. В иных случаях:- Методом ветвей и границ
- Методом динамического программирования
Метод динамического программирования
Пусть
максимальная стоимость любого возможного числа вещей типов от 1 до , суммарным весом до .Заполним
нулями.Тогда меняя i от 1 до
, расчитаем на каждом шаге от 0 до по рекурентной формуле:
Если не нужно востанавливать ответ, то можно использовать одномерный массив
вместо двумерного.Сложность алгоритма
.Непрерывный рюкзак
""Непрерывный рюкзак"" (англ. "Continuous knapsack problem") -обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз.
Формулировка Задачи
Каждый предмет может быть выбран ограниченное
число раз. Задача выбрать число предметов каждого типа так, чтобымаксимизировать общую стоимость:
выполнялось условие на совместность:
и
для всехВарианты решения
При небольших
решается сведением к классической задаче о рюкзаке. В иных случаях:- Методом ветвей и границ
- Методом динамического программирования
Метод динамического программирования
Пусть
максимальная стоимость любого возможного числа вещей типов от 1 до , суммарным весом до .Заполним
нулями.Тогда меняя i от 1 до
, расчитаем на каждом шаге от 0 до по рекурентной формуле:
Если не нужно востанавливать ответ, то можно использовать одномерный массив
вместо двумерного.Сложность алгоритма
.Литература
- Дистанционная подготовка по информатике
- Код для нескольких задач семейства на всевозможных языках
- David Pisinger Knapsack problems. — 1995
- Knapsack Problems: Algorithms and Computer Implementations. Silvano Martello, Paolo Toth.