Задача о рюкзаке — различия между версиями
Енгулатов (обсуждение | вклад) (Исправлен всевдокод. Заменены max. Исправлена плохочитаемый текст. Добавлено см. И т. д.) |
Енгулатов (обсуждение | вклад) м |
||
| Строка 1: | Строка 1: | ||
{{Задача | {{Задача | ||
|definition = | |definition = | ||
| − | '''Задача о рюкзаке'''('' англ. Knapsack problem'') — дано <tex>N</tex> предметов, <tex>n_i</tex> предмет имеет массу <tex> w_i > 0</tex> и стоимость <tex> p_i > 0</tex>. Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины <tex>W</tex> (вместимость рюкзака), а суммарная стоимость была максимальна. | + | '''Задача о рюкзаке '''(''англ. Knapsack problem'') — дано <tex>N</tex> предметов, <tex>n_i</tex> предмет имеет массу <tex> w_i > 0</tex> и стоимость <tex> p_i > 0</tex>. Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины <tex>W</tex> (вместимость рюкзака), а суммарная стоимость была максимальна. |
}} | }} | ||
Версия 01:51, 5 июня 2017
| Задача: |
| Задача о рюкзаке (англ. 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] //иначе, не кладем
Затем найдем набор предметов, входящих в рюкзак, рекурсивной функцией:
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)
Сложность алгоритма
Пример
| 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]) to 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
- Метод четырех русских для умножения матриц
- Задача о редакционном расстоянии, алгоритм Вагнера-Фишера
Источники информации
- Дистанционная подготовка по информатике
- Код для нескольких задач семейства на всевозможных языках
- David Pisinger Knapsack problems. — 1995
- Silvano Martello, Paolo Toth. Knapsack Problems: Algorithms and Computer Implementations — 1990 г. — ISBN 0-471-92420-2