Задача о рюкзаке — различия между версиями
Енгулатов (обсуждение | вклад) (→Реализация) |
м (rollbackEdits.php mass rollback) |
||
(не показано 26 промежуточных версий 9 участников) | |||
Строка 23: | Строка 23: | ||
== Метод динамического программирования == | == Метод динамического программирования == | ||
− | Пусть <tex>A(k, s)</tex> есть максимальная | + | Пусть <tex>A(k, s)</tex> есть максимальная стоимость предметов, которые можно уложить в рюкзак вместимости <tex>s</tex>, если можно использовать только первые <tex>k</tex> предметов, то есть <tex>\{n_1,n_2,\dots,n_k\}</tex>, назовем этот набор допустимых предметов для <tex>A(k,s)</tex>. |
<tex>A(k, 0) = 0</tex> | <tex>A(k, 0) = 0</tex> | ||
Строка 56: | Строка 56: | ||
Заметим, что при построении <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> не входит в искомый набор, иначе входит. | ||
− | Метод динамического программирование всё равно не | + | Метод динамического программирование всё равно не позволяет решать задачу за полиномиальное время, потому что его сложность зависит от максимального веса. Задача о ранце (или задача о рюкзаке) — одна из [[Класс NP|NP-полных]] задач комбинаторной оптимизации. |
== Реализация == | == Реализация == | ||
Сначала генерируем <tex>A</tex>. | Сначала генерируем <tex>A</tex>. | ||
− | '''for''' i = 0 to w | + | '''for''' i = 0 '''to''' w |
A[0][i] = 0 | A[0][i] = 0 | ||
− | '''for''' i = 0 to n | + | '''for''' i = 0 '''to''' n |
− | A[i][0] = 0 ''<font color="green">// Первые элементы приравниваем к 0</font>'' | + | A[i][0] = 0 ''<font color="green">//Первые элементы приравниваем к 0</font>'' |
− | '''for''' k = 1 to n | + | '''for''' k = 1 '''to''' n |
− | '''for''' s = 1 to w ''<font color="green">//Перебираем для каждого k все вместимости</font>'' | + | '''for''' s = 1 '''to''' w ''<font color="green">//Перебираем для каждого k все вместимости</font>'' |
'''if''' s >= w[k] ''<font color="green">//Если текущий предмет вмещается в рюкзак</font>'' | '''if''' s >= w[k] ''<font color="green">//Если текущий предмет вмещается в рюкзак</font>'' | ||
− | A[k][s] = max(A[k - 1][s], A[k - 1][s - w[k]] + p[k]) ''<font color="green">// | + | A[k][s] = max(A[k - 1][s], A[k - 1][s - w[k]] + p[k]) ''<font color="green">//Выбираем класть его или нет</font>'' |
'''else''' | '''else''' | ||
− | A[k][s] = A[k - 1][s] ''<font color="green">// | + | A[k][s] = A[k - 1][s] ''<font color="green">//Иначе, не кладем</font>'' |
Затем найдем набор <tex>ans</tex> предметов, входящих в рюкзак, рекурсивной функцией: | Затем найдем набор <tex>ans</tex> предметов, входящих в рюкзак, рекурсивной функцией: | ||
Строка 126: | Строка 126: | ||
'''Восстановление набора предметов, из которых состоит максимально дорогой рюкзак.''' | '''Восстановление набора предметов, из которых состоит максимально дорогой рюкзак.''' | ||
− | Начиная с <tex>A(5, 13)</tex> восстанавливаем ответ. Будем идти в обратном порядке по <tex>k</tex>. ''<font color=" | + | Начиная с <tex>A(5, 13)</tex> восстанавливаем ответ. Будем идти в обратном порядке по <tex>k</tex>. ''<font color="000000">Красным фоном обозначим наш путь</font>'' |
{|border="1" class="wikitable" style="text-align:center" width="75%" | {|border="1" class="wikitable" style="text-align:center" width="75%" | ||
Строка 152: | Строка 152: | ||
=Другие задачи семейства= | =Другие задачи семейства= | ||
+ | ==Ограниченный рюкзак== | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
Строка 157: | Строка 158: | ||
}} | }} | ||
− | |||
− | |||
===Формулировка Задачи=== | ===Формулировка Задачи=== | ||
Строка 182: | Строка 181: | ||
Тогда меняя i от 1 до <tex>N</tex>, рассчитаем на каждом шаге <tex>d(i,c)</tex>, для <tex>c</tex> от 1 до <tex>W</tex>, по рекуррентной формуле: | Тогда меняя i от 1 до <tex>N</tex>, рассчитаем на каждом шаге <tex>d(i,c)</tex>, для <tex>c</tex> от 1 до <tex>W</tex>, по рекуррентной формуле: | ||
− | <tex>d(i,c) = \max(d(i - 1, c - lw_i) + lp_i) </tex> по всем целым <tex> l </tex> из промежутка <tex> 0 \leqslant l \leqslant min(b_i,\lfloor c/w_i \rfloor)</tex>. | + | <tex>d(i,c) = \max(d(i, c), d(i - 1, c - lw_i) + lp_i) </tex> по всем целым <tex> l </tex> из промежутка <tex> 0 \leqslant l \leqslant min(b_i,\lfloor c/w_i \rfloor)</tex>. |
Если не нужно восстанавливать ответ, то можно использовать одномерный массив <tex>d(c)</tex> вместо двумерного. | Если не нужно восстанавливать ответ, то можно использовать одномерный массив <tex>d(c)</tex> вместо двумерного. | ||
Строка 189: | Строка 188: | ||
=== Реализация === | === Реализация === | ||
− | '''for''' i = 0 to | + | '''for''' i = 0 '''to''' w ''<font color="green">//База</font>'' |
d[0][i] = 0 | d[0][i] = 0 | ||
− | '''for''' i = 1 to | + | '''for''' i = 1 '''to''' n |
− | '''for''' c = 1 to | + | '''for''' c = 1 '''to''' w ''<font color="green">//Перебираем для каждого i, все вместимости </font>'' |
d[i][c] = d[i - 1][c] | d[i][c] = d[i - 1][c] | ||
− | '''for''' l = min(b[i], c / w[i]) | + | '''for''' l = min(b[i], c / w[i]) '''downto''' 1 ''<font color="green">//Ищем l для которого выполняется максимум </font>'' |
d[i][c] = max(d[i][c], d[i - 1][c - l * w[i]] + p[i] * l) | d[i][c] = max(d[i][c], d[i - 1][c - l * w[i]] + p[i] * l) | ||
Сложность алгоритма <tex>O(NW^2)</tex>. | Сложность алгоритма <tex>O(NW^2)</tex>. | ||
− | + | ==Неограниченный рюкзак== | |
{{Задача | {{Задача | ||
|definition = | |definition = | ||
'''Неограниченный рюкзак''' (англ.''Unbounded Knapsack Problem'') — обобщение ограниченного рюкзака, в котором любой предмет может быть выбран любое количество раз. | '''Неограниченный рюкзак''' (англ.''Unbounded Knapsack Problem'') — обобщение ограниченного рюкзака, в котором любой предмет может быть выбран любое количество раз. | ||
}} | }} | ||
− | |||
− | |||
− | |||
===Формулировка Задачи=== | ===Формулировка Задачи=== | ||
Строка 223: | Строка 219: | ||
===Метод динамического программирования=== | ===Метод динамического программирования=== | ||
− | Пусть <tex>d(i,c)</tex> максимальная стоимость любого количества вещей типов от 1 до <tex>i</tex>, суммарным весом до <tex>c</tex> включительно. | + | Пусть <tex>d(i,c)</tex> - максимальная стоимость любого количества вещей типов от 1 до <tex>i</tex>, суммарным весом до <tex>c</tex> включительно. |
Заполним <tex>d(0,c)</tex> нулями. | Заполним <tex>d(0,c)</tex> нулями. | ||
Строка 245: | Строка 241: | ||
Сложность алгоритма <tex>O(NW)</tex>. | Сложность алгоритма <tex>O(NW)</tex>. | ||
+ | ==Непрерывный рюкзак== | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
− | '''Непрерывный рюкзак''' (англ. ''Continuous knapsack problem'') — вариант задачи, в котором возможно брать | + | '''Непрерывный рюкзак''' (англ. ''Continuous knapsack problem'') — вариант задачи, в котором возможно брать любую дробную часть от предмета, при этом удельная стоимость сохраняется. |
}} | }} | ||
− | |||
− | |||
− | |||
===Формулировка Задачи=== | ===Формулировка Задачи=== | ||
Строка 266: | Строка 260: | ||
=== Реализация === | === Реализация === | ||
− | sort() | + | sort() ''<font color="green">//Сортируем в порядке убывания удельной стоимости.</font>'' |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | '''for''' i = 1 '''to''' n ''<font color="green">//Идем по предметам </font>'' | ||
+ | '''if''' w > w[i] ''<font color="green">//Если помещается — берем</font>'' | ||
+ | sum += p[i] | ||
+ | w -= w[i] | ||
+ | '''else''' | ||
+ | sum += w / w[i] * p[i] ''<font color="green">//Иначе берем сколько можно и выходим</font>'' | ||
+ | '''break''' | ||
+ | |||
+ | ==Задача о суммах подмножеств== | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
− | '''Задача о суммах подмножеств''' (англ. '' | + | '''Задача о суммах подмножеств''' (англ. ''Subset sum problem, Value Independent Knapsack Problem'') — задача из семейства, в которой стоимость предмета совпадает с его весом. |
}} | }} | ||
− | |||
− | |||
− | |||
===Формулировка Задачи=== | ===Формулировка Задачи=== | ||
Строка 295: | Строка 288: | ||
Для решения пригодны любые методы применяемые для классической задачи, однако специализированые алгоритмы обычно более оптимальны по параметрам. Используются: | Для решения пригодны любые методы применяемые для классической задачи, однако специализированые алгоритмы обычно более оптимальны по параметрам. Используются: | ||
* Метод динамического программирования. | * Метод динамического программирования. | ||
− | * | + | * Использовать различные сложные алгоритмы <ref>http://hjemmesider.diku.dk/~pisinger/codes.html</ref><ref>Pisinger D (1999). "Linear Time Algorithms for Knapsack Problems with Bounded Weights". ''Journal of Algorithms'', Volume 33, Number 1, October 1999, pp. 1–14</ref><ref>Koiliaris, Konstantinos; Xu, Chao (2015-07-08). "A Faster Pseudopolynomial Time Algorithm for Subset Sum".</ref><ref>Bringmann K. A near-linear pseudopolynomial time algorithm for subset sum[C]//Proceedings of the Twenty-Eighth Annual ACM-SIAM Symposium on Discrete Algorithms. Society for Industrial and Applied Mathematics, 2017: 1073-1084</ref>. |
===Метод динамического программирования=== | ===Метод динамического программирования=== | ||
Строка 316: | Строка 309: | ||
Сложность алгоритма <tex>O(NW)</tex>. | Сложность алгоритма <tex>O(NW)</tex>. | ||
+ | ==Задача о размене== | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
Строка 359: | Строка 353: | ||
Сложность алгоритма <tex>O(NW)</tex>. | Сложность алгоритма <tex>O(NW)</tex>. | ||
+ | ==Задача об упаковке== | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
'''Задача об упаковке''' (англ. ''Bin Packing Problem'') — имеются <tex> N </tex> рюкзаков вместимости <tex> W </tex> и столько же предметов с весами <tex>w_i</tex>. Нужно распределить все предметы, задействовав минимальное количество рюкзаков. | '''Задача об упаковке''' (англ. ''Bin Packing Problem'') — имеются <tex> N </tex> рюкзаков вместимости <tex> W </tex> и столько же предметов с весами <tex>w_i</tex>. Нужно распределить все предметы, задействовав минимальное количество рюкзаков. | ||
}} | }} | ||
− | |||
− | |||
− | |||
===Формулировка Задачи=== | ===Формулировка Задачи=== | ||
Строка 381: | Строка 373: | ||
Применение динамического программирования нецелесообразно. Обычно применяют аппроксимационные алгоритмы, либо используют метод ветвей и границ. | Применение динамического программирования нецелесообразно. Обычно применяют аппроксимационные алгоритмы, либо используют метод ветвей и границ. | ||
+ | ==Мультипликативный рюкзак== | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
'''Мультипликативный рюкзак''' (англ. ''Multiple Knapsack Problem'') — есть <tex>N</tex> предметов и <tex>M</tex> рюкзаков (<tex>M\leqslant N</tex>). У каждого рюкзака своя вместимость <tex>W_i</tex>. Задача: выбрать <tex>M</tex> не пересекающихся множеств, назначить соответствие рюкзакам так, чтобы суммарная стоимость была максимальна, а вес предметов в каждом рюкзаке не превышал его вместимость. | '''Мультипликативный рюкзак''' (англ. ''Multiple Knapsack Problem'') — есть <tex>N</tex> предметов и <tex>M</tex> рюкзаков (<tex>M\leqslant N</tex>). У каждого рюкзака своя вместимость <tex>W_i</tex>. Задача: выбрать <tex>M</tex> не пересекающихся множеств, назначить соответствие рюкзакам так, чтобы суммарная стоимость была максимальна, а вес предметов в каждом рюкзаке не превышал его вместимость. | ||
}} | }} | ||
− | |||
− | |||
− | |||
===Формулировка Задачи=== | ===Формулировка Задачи=== | ||
Строка 402: | Строка 392: | ||
Применение динамического программирования, для задач данного типа нецелесообразно. Используются вариации метода ветвей и границ. | Применение динамического программирования, для задач данного типа нецелесообразно. Используются вариации метода ветвей и границ. | ||
+ | ==Задача о назначении== | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
'''Задача о назначении''' (англ. ''Generalized Assignment Problem'') — Наиболее общая задача семейства. Отличается от мультипликативного рюкзака тем, что каждый предмет имеет различные характеристики в зависимости от рюкзака, куда его помещают. Есть <tex>N</tex> предметов и <tex>M</tex> рюкзаков (<tex>M\leqslant N</tex>). У каждого рюкзака своя вместимость <tex>W_i</tex>, у <tex> j </tex> предмета <tex> p_{ij} </tex> стоимость и вес, при помещении его в <tex> i </tex> рюкзак, равны <tex> p_{ij} </tex> и <tex> w_{ij} </tex> соответственно. | '''Задача о назначении''' (англ. ''Generalized Assignment Problem'') — Наиболее общая задача семейства. Отличается от мультипликативного рюкзака тем, что каждый предмет имеет различные характеристики в зависимости от рюкзака, куда его помещают. Есть <tex>N</tex> предметов и <tex>M</tex> рюкзаков (<tex>M\leqslant N</tex>). У каждого рюкзака своя вместимость <tex>W_i</tex>, у <tex> j </tex> предмета <tex> p_{ij} </tex> стоимость и вес, при помещении его в <tex> i </tex> рюкзак, равны <tex> p_{ij} </tex> и <tex> w_{ij} </tex> соответственно. | ||
}} | }} | ||
− | |||
− | |||
− | |||
Весьма важная задача, так как она моделирует оптимальное распределение различных задач между вычислительными блоками. | Весьма важная задача, так как она моделирует оптимальное распределение различных задач между вычислительными блоками. | ||
Строка 417: | Строка 405: | ||
при выполнении условия совместности <tex>\sum_{j=1}^N w_{ij} x_{ij} \leqslant W_i \qquad i=1, \ldots, M</tex>. | при выполнении условия совместности <tex>\sum_{j=1}^N w_{ij} x_{ij} \leqslant W_i \qquad i=1, \ldots, M</tex>. | ||
− | <tex> \sum_{i=1}^M x_{ij} \ | + | <tex> \sum_{i=1}^M x_{ij} \leqslant 1 \qquad j=1, \ldots, N</tex>. |
<tex> x_{ij} \in \{0,1\} \qquad i=1, \ldots, N, \quad j=1, \ldots, N</tex>. | <tex> x_{ij} \in \{0,1\} \qquad i=1, \ldots, N, \quad j=1, \ldots, N</tex>. |
Текущая версия на 19:19, 4 сентября 2022
Задача: |
Задача о рюкзаке (англ. Knapsack problem) — дано | предметов, предмет имеет массу и стоимость . Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины (вместимость рюкзака), а суммарная стоимость была максимальна.
Содержание
- 1 Формулировка задачи
- 2 Варианты решения
- 3 Метод динамического программирования
- 4 Реализация
- 5 Пример
- 6 Другие задачи семейства
Формулировка задачи
Дано
предметов, — вместимость рюкзака, — соответствующий ему набор положительных целых весов, — соответствующий ему набор положительных целых стоимостей. Нужно найти набор бинарных величин , где , если предмет включен в набор, , если предмет не включен, и такой что:- максимальна.
Варианты решения
Задачу о рюкзаке можно решить несколькими способами:
- Перебирать все подмножества набора из N предметов. Сложность такого решения .
- Методом Meet-in-the-middle. Сложность решения
- Метод динамического программирования. Сложность — .
Метод динамического программирования
Пусть
есть максимальная стоимость предметов, которые можно уложить в рюкзак вместимости , если можно использовать только первые предметов, то есть , назовем этот набор допустимых предметов для .
Найдем
. Возможны 2 варианта:- Если предмет не попал в рюкзак. Тогда равно максимальной стоимости рюкзака с такой же вместимостью и набором допустимых предметов , то есть
- Если попал в рюкзак. Тогда равно максимальной стоимости рюкзака, где вес уменьшаем на вес -ого предмета и набор допустимых предметов плюс стоимость , то есть
То есть:
Стоимость искомого набора равна
, так как нужно найти максимальную стоимость рюкзака, где все предметы допустимы и вместимость рюкзака .Восстановим набор предметов, входящих в рюкзак
Будем определять, входит ли
предмет в искомый набор. Начинаем с элемента , где , . Для этого сравниваем со следующими значениями:- Максимальная стоимость рюкзака с такой же вместимостью и набором допустимых предметов , то есть
- Максимальная стоимость рюкзака с вместимостью на меньше и набором допустимых предметов плюс стоимость , то есть
Заметим, что при построении
мы выбирали максимум из этих значений и записывали в . Тогда будем сравнивать c , если равны, тогда не входит в искомый набор, иначе входит.Метод динамического программирование всё равно не позволяет решать задачу за полиномиальное время, потому что его сложность зависит от максимального веса. Задача о ранце (или задача о рюкзаке) — одна из NP-полных задач комбинаторной оптимизации.
Реализация
Сначала генерируем
.for i = 0 to w A[0][i] = 0 for i = 0 to n A[i][0] = 0 //Первые элементы приравниваем к 0 for k = 1 to n for s = 1 to 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] //Иначе, не кладем
Затем найдем набор
предметов, входящих в рюкзак, рекурсивной функцией:function findAns(int k, int 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)
Сложность алгоритма
Пример
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 |
k = 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
k = 2 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 7 | 7 | 7 | 7 | 7 |
k = 3 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 11 | 11 |
k = 4 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
k = 5 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
Числа от 0 до 13 в первой строчке обозначают вместимость рюкзака.
В первой строке как только вместимость рюкзака
, добавляем в рюкзак 1 предмет.Рассмотрим
, при каждом так как сравниваем и и записываем в стоимость либо рюкзака без третьего предмета, но с таким же весом, либо с третьим предметом, тогда стоимость равна стоимости третьего предмета плюс стоимость рюкзака с вместимостью на меньше.Максимальная стоимость рюкзака находится в
.Восстановление набора предметов, из которых состоит максимально дорогой рюкзак.
Начиная с
восстанавливаем ответ. Будем идти в обратном порядке по . Красным фоном обозначим наш путь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 |
k = 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
k = 2 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 7 | 7 | 7 | 7 | 7 |
k = 3 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 11 | 11 |
k = 4 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
k = 5 | 0 | 0 | 1 | 6 | 6 | 6 | 7 | 7 | 10 | 10 | 10 | 13 | 13 |
Таким образом, в набор входит
и предмет.Стоимость рюкзака:
Вес рюкзака:
Другие задачи семейства
Ограниченный рюкзак
Задача: |
Ограниченный рюкзак (англ. Bounded Knapsack Problem) — обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз. |
Формулировка Задачи
Каждый предмет может быть выбран ограниченное
число раз. Задача выбрать число предметов каждого типа так, чтобы- максимизировать общую стоимость: ;
- выполнялось условие совместности: ;
где
для всех .Варианты решения
При небольших
решается сведением к классической задаче о рюкзаке. В иных случаях:- Методом ветвей и границ.
- Методом динамического программирования.
Метод динамического программирования
Пусть
максимальная стоимость любого возможного числа предметов типов от 1 до , суммарным весом до .Заполним
нулями.Тогда меняя i от 1 до
, рассчитаем на каждом шаге , для от 1 до , по рекуррентной формуле:по всем целым из промежутка .
Если не нужно восстанавливать ответ, то можно использовать одномерный массив
вместо двумерного.После выполнения в
будет лежать максимальная стоимость предметов, помещающихся в рюкзак.Реализация
for i = 0 to w //База d[0][i] = 0 for i = 1 to n for c = 1 to w //Перебираем для каждого i, все вместимости d[i][c] = d[i - 1][c] for l = min(b[i], c / w[i]) downto 1 //Ищем l для которого выполняется максимум d[i][c] = max(d[i][c], d[i - 1][c - l * w[i]] + p[i] * l)
Сложность алгоритма
.Неограниченный рюкзак
Задача: |
Неограниченный рюкзак (англ.Unbounded Knapsack Problem) — обобщение ограниченного рюкзака, в котором любой предмет может быть выбран любое количество раз. |
Формулировка Задачи
Каждый предмет может быть выбран любое число раз. Задача выбрать количество
предметов каждого типа так, чтобы- максимизировать общую стоимость: ;
- выполнялось условие совместности: ;
где
целое, для всех .Варианты решения
Самые распространенные методы точного решения это:
- Метод ветвей и границ.
- Метод динамического программирования.
Метод динамического программирования
Пусть
- максимальная стоимость любого количества вещей типов от 1 до , суммарным весом до включительно.Заполним
нулями.Тогда меняя i от 1 до
, рассчитаем на каждом шаге , для от 0 до , по рекуррентной формуле:
После выполнения в
будет лежать максимальная стоимость предметов, помещающихся в рюкзак.Если не нужно восстанавливать ответ, то можно использовать одномерный массив
вместо двумерного и использовать формулу:;
Сложность алгоритма
.Непрерывный рюкзак
Задача: |
Непрерывный рюкзак (англ. Continuous knapsack problem) — вариант задачи, в котором возможно брать любую дробную часть от предмета, при этом удельная стоимость сохраняется. |
Формулировка Задачи
Задача выбрать часть
каждого предмета так, чтобы- максимизировать общую стоимость: ;
- выполнялось условие совместности: ;
где
дробное, для всех .Варианты решения
Возможность брать любую часть от предмета сильно упрощает задачу. Жадный алгоритм дает оптимальное решение в данном случае.
Реализация
sort() //Сортируем в порядке убывания удельной стоимости.
for i = 1 to n //Идем по предметам if w > w[i] //Если помещается — берем sum += p[i] w -= w[i] else sum += w / w[i] * p[i] //Иначе берем сколько можно и выходим break
Задача о суммах подмножеств
Задача: |
Задача о суммах подмножеств (англ. Subset sum problem, Value Independent Knapsack Problem) — задача из семейства, в которой стоимость предмета совпадает с его весом. |
Формулировка Задачи
Нужно выбрать подмножество так, чтобы сумма ближе всего к
, но не превысила его. Формально, нужно найти набор бинарных величин , так чтобы- максимизировать общую стоимость: ;
- выполнялось условие совместности: ;
если предмет назначен рюкзаку, иначе , для всех .
Варианты решения
Для решения пригодны любые методы применяемые для классической задачи, однако специализированые алгоритмы обычно более оптимальны по параметрам. Используются:
Метод динамического программирования
Пусть
максимальная сумма , подмножества взятого из элементов.Заполним
нулями.Тогда меняя i от 1 до
, рассчитаем на каждом шаге , для от 0 до , по рекуррентной формуле:
После выполнения в
будет лежать максимальная сумма подмножества, не превышающая заданное значение.Сложность алгоритма
.Задача о размене
Задача: |
Задача о размене (англ. Change-Making problem) — имеются | неисчерпаемых типов предметов с весами . Нужно наполнить рюкзак предметами с суммарным весом .
Часто задачу ставят как, дать сдачу наименьшим количеством монет.
Формулировка Задачи
Каждый предмет может быть выбран любое число раз. Задача выбрать количество
предметов каждого типа так, чтобы- минимизировать количество взятых предметов: ;
- сумма весов выбранных предметов равнялась вместимости рюкзака: ;
Где
целое, для всех .Варианты решения
Самые распространенные методы точного решения это:
- Метод ветвей и границ.
- Метод динамического программирования.
Метод динамического программирования
Пусть
минимальное число предметов, типов от 1 до , необходимое, чтобы заполнить рюкзак вместимостью .Пусть
, а для всех .Тогда меняя i от 1 до
, рассчитаем на каждом шаге , для от 0 до , по рекуррентной формуле:
После выполнения в
будет лежать максимальная стоимость предметов, помещающихся в рюкзак.Если не нужно восстанавливать ответ, то можно использовать одномерный массив
вместо двумерного и использовать формулу:.
Сложность алгоритма
.Задача об упаковке
Задача: |
Задача об упаковке (англ. Bin Packing Problem) — имеются | рюкзаков вместимости и столько же предметов с весами . Нужно распределить все предметы, задействовав минимальное количество рюкзаков.
Формулировка Задачи
Математически задачу можно представить так:
- минимизировать количество рюкзаков: ;
- так чтобы выполнялось условие на совместность: ;
если предмет назначен рюкзаку. Иначе .
если рюкзак используется. Иначе .
Варианты решения
Применение динамического программирования нецелесообразно. Обычно применяют аппроксимационные алгоритмы, либо используют метод ветвей и границ.
Мультипликативный рюкзак
Задача: |
Мультипликативный рюкзак (англ. Multiple Knapsack Problem) — есть | предметов и рюкзаков ( ). У каждого рюкзака своя вместимость . Задача: выбрать не пересекающихся множеств, назначить соответствие рюкзакам так, чтобы суммарная стоимость была максимальна, а вес предметов в каждом рюкзаке не превышал его вместимость.
Формулировка Задачи
Максимизировать
так, чтобы
выполнялось для всех .для всех .
если предмет назначен рюкзаку. Иначе .
Варианты решения
Применение динамического программирования, для задач данного типа нецелесообразно. Используются вариации метода ветвей и границ.
Задача о назначении
Задача: |
Задача о назначении (англ. Generalized Assignment Problem) — Наиболее общая задача семейства. Отличается от мультипликативного рюкзака тем, что каждый предмет имеет различные характеристики в зависимости от рюкзака, куда его помещают. Есть | предметов и рюкзаков ( ). У каждого рюкзака своя вместимость , у предмета стоимость и вес, при помещении его в рюкзак, равны и соответственно.
Весьма важная задача, так как она моделирует оптимальное распределение различных задач между вычислительными блоками.
Формулировка Задачи
Максимизировать стоимость выбранных предметов
,при выполнении условия совместности
..
.
Варианты решения
Применение динамического программирования нецелесообразно. Наиболее используем метод ветвей и границ.
См. также
- Класс NP
- Метод четырех русских для умножения матриц
- Задача о редакционном расстоянии, алгоритм Вагнера-Фишера
- Meet-in-the-middle
Источники информации
- Дистанционная подготовка по информатике
- Код для нескольких задач семейства на всевозможных языках
- David Pisinger Knapsack problems. — 1995
- Silvano Martello, Paolo Toth. Knapsack Problems: Algorithms and Computer Implementations — 1990 г. — ISBN 0-471-92420-2
- ↑ http://hjemmesider.diku.dk/~pisinger/codes.html
- ↑ Pisinger D (1999). "Linear Time Algorithms for Knapsack Problems with Bounded Weights". Journal of Algorithms, Volume 33, Number 1, October 1999, pp. 1–14
- ↑ Koiliaris, Konstantinos; Xu, Chao (2015-07-08). "A Faster Pseudopolynomial Time Algorithm for Subset Sum".
- ↑ Bringmann K. A near-linear pseudopolynomial time algorithm for subset sum[C]//Proceedings of the Twenty-Eighth Annual ACM-SIAM Symposium on Discrete Algorithms. Society for Industrial and Applied Mathematics, 2017: 1073-1084