исчерпывающий поиск1.ppt
- Количество слайдов: 85
исчерпывающий поиск 1
Характеристика методов исчерпывающего поиска • Методы исчерпывающего поиска предполагают генерацию всех решений и выбор из них решения с требуемыми свойствами. • С учётом быстродействия ЭВМ исчерпывающий поиск эффективен в множестве, состоящем не более чем из 108 элементов. Поэтому для того, чтобы эти методы были полезны, к ним нужно относиться как к схемам, с которыми следует подходить к задаче. • Схемы должны быть хорошо приспособлены к конкретной задаче, так чтобы в результате алгоритм годился для практического использования, а это требует большей изобретательности. 2
Задачи, где целесообразно использовать методы исчерпывающего поиска • • • Комбинаторика Теория графов Теория расписания грамматический разбор, игры и т. д. , Т. е. там, где альтернативы перебору нет 3
К методам исчерпывающего поиска можно отнести: – метод проб и ошибок или поиск с возвращением; – метод ветвей и границ; – динамическое программирование; – методы решета; – приближения исчерпывающего поиска • эвристические алгоритмы; • жадные алгоритмы. 4
Принципиальная характеристика поиска с возвращением • Поиск с возвращением работает постоянно пытаясь расширить частичное решение. На каждом шаге поиска, если расширение текущего частичного решения невозможно, мы возвращаемся к более короткому частичному решению и пытаемся снова его продолжить. • Этот метод, по-английски называемый backtracking (некоторые авторы и по-русски пишут «бектрекинг» ), основан на методе поиска в глубину. • Поскольку речь идет о переборе дерева вариантов методом поиска в глубину, то во время работы алгоритма текущий путь в дереве 5 хранится в виде стека.
Принципиальная характеристика метода ветвей и границ • Если алгоритм с возвратом направлен на нахождение одного или нескольких решений, удовлетворяющих определенным условиям, то алгоритмы ветвей и границ ориентированы преимущественно на оптимизацию. • В дереве решений для каждого узла (вершины) определяется некоторая функция стоимости. Цель — найти конфигурацию, на которой функция стоимости достигает максимального или минимального значения. • Алгоритмы ветвей и границ, как правило, довольно сложны. Для сокращения процесса поиска оптимального решения используется метод поиска, основанный на правилах вычеркивания ветвей. 6
Принципиальная характеристика динамического программирования • Динамическое программирование обычно применяется к задачам, в которых искомый ответ состоит из частей, каждая из которых в свою очередь даёт оптимальное решение некоторой подзадачи. • Динамическое программирование полезно, если на разных путях многократно встречаются одни и те же подзадачи; • основной технический приём — запоминать решения встречающихся подзадач на случай, если та же подзадача встретится вновь. 7
Принципиальная характеристика метода решета • Метод решета, является логическим дополнением к поиску с возвращением; при его использовании мы пытаемся исключить объекты, не являющиеся решениями, вместо того, чтобы искать сами решения. Методы решета полезны прежде всего в теоретико-числовых задачах. • Нужно помнить, однако, что поиск с возвращением и метод решета представляют собой только общие методы. Непосредственное их применение обычно ведет к алгоритмам, время работы которых недопустимо велико. 8
Принципиальная характеристика эвристических алгоритмов • Для трудных с вычислительной точки зрения проблем один из подходов состоит в том, чтобы требовать результат близкий к оптимальному. Ослабление ограничений на оптимальность часто приводит к более эффективным алгоритмам, поскольку в этом случае исчерпывающий поиск является только «приближенным» . При этом ожидается, что проигрыш в стоимости найденных (квазиоптимальных) решений будет умеренным. • Не трудно изобрести эвристические алгоритмы, которые быстро находят решение; в действительности, можно обнаружить, что большинство, но не все решения, получаемые эвристикой, являются хорошими. • Теоретически невозможно доказать, что эвристический алгоритм всегда находит решение, близкое к оптимальному. 9
Принципиальная характеристика жадных алгоритмов • Жадные алгоритмы, как и динамическое программирование, применяются в тех случаях, когда искомый объект строится по частям. Жадный алгоритм делает на каждом шаге “локально оптимальный” выбор. • Простой пример: стараясь набрать данную сумму денег минимальным числом монет, можно последовательно брать монеты наибольшего возможного достоинства (не превосходящего той суммы, которую осталось набрать). • Жадный алгоритм обычно работает гораздо быстрее, чем алгоритм, основанный на динамическом программировании. Однако жадный алгоритм вовсе не всегда даёт оптимальное решение. Во многих задачах применимость жадных алгоритмов удаётся доказать с помощью так называемых матроидов. 10
Метод проб и ошибок или поиск с возвращением Идею поиска с возвращением легче всего понять в связи с задачей прохода через лабиринт. Один из способов прохода через лабиринт — это двигаться из начального квадрата в соответствии с двумя правилами: 1. В каждом квадрате выбирать еще не исследованный путь. 2. Если из исследуемого в данный момент квадрата ведут исследованные пути, то нужно вернуться на один квадрат назад по последнему пройденному пути, по которому вы пришли в данный квадрат и выполнить п. 1. Первое правило говорит о том, как расширить исследуемый путь, если это возможно, а второе правило — о том, как выходить из тупика. 11
Постановка задачи - проход через лабиринт • Лабиринт, состоящий из проходимых и непроходимых клеток, задан матрицей A размером M*N. Элемент матрицы A[i, j]=1, если клетка (i, j) проходима. В противном случае A[i, j]=0. • Требуется найти кратчайший путь из клетки (1, 1) в клетку (M 1, N 1). • Фактически лабиринт представляет собой граф с соответствующей матрицей смежности. • Заметим, что алгоритм можно усовершенствовать, если не позволять, чтобы длина пути (Way) была больше или равна длине оптимального пути (Optimal. Way). 12
Пример 1 2 5 3 4 Посмотрим работу алгоритма на примере лабиринта, изображенного на рисунке. Фиксируем порядок посещения конец соседних клеток: левая, верхняя, правая, нижняя. В таблице 5 будем фиксировать лишь содержимое Way и Optimal. Way в моменты переходов от движения вперед к возврату назад и наоборот от возвратов назад к движению вперед. 4 Содержимое Way Содержимое Optimal. Way <(1, 1)> Бесконечно путь “движение вперед”<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1), (5, 1)> тупик /– то же –/ “возврат”…<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1)> /– то же –/ “движение вперед”<(1, 1), (1, 2), (2, 2), (3, 1), (4, 2), (4, 3), (5, 2)> тупик /– то же –/ “возврат”…<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1) (4, 2), (4, 3)> /– то же –/ “движение вперед”<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1) (4, 2), (4, 3), (4, 4), (4, 5), (5, 4)>найден вариант. <(1, 1), (1, 2), (2, 2), (3, 1), (4, 2), (4, 3), (4, 4), ( 4, 5), (5, 4)> “возврат”…<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1) (4, 2), (4, 3), (4, 4), (4, 5)> /– то же –/ 3 2 1 начало Pиc. 1. Лабиринт длинный 13
Пример (продолжение) “движение вперед”<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1) (4, 2), (4, 3), (4, 4), (4, 5), (3, 5), (2, 5), (1, 4), (1, 3), (2, 3)> тупик 2 /– то же –/ “возврат”…<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1) (4, 2), (4, 3) /– то же –/ “движение вперед””…<(1, 1), (1, 2), (2, 2), (3, 1), (4, 1) (4, 2), (4, 3), (3, 4), (2, 3)> тупик /– то же –/ возврат”…<(1, 1), (1, 2), (2, 2), (3, 3), (4, 3) > /– то же –/ “движение вперед”<(1, 1), (1, 2), (2, 2), (3, 3), (4, 3), (3, 4), (2, 4) > тупик /– то же –/ “возврат” <(1, 1), (1, 2), (2, 2), (3, 2)> /– то же –/ “движение вперед”<(1, 1), (1, 2), (2, 2), (3, 3), (4, 2), (4, 1), (5, 1)> тупик /– то же –/ “возврат” <(1, 1), (1, 2), (2, 3), (3, 3), (4, 3)> /– то же –/ “движение вперед”<(1, 1), (1, 2), (2, 3), (3, 3), (4, 3), (5, 2)> тупик /– то же –/ “возврат” <(1, 1), (1, 2), (2, 3), (3, 3), (4, 3)> /– то же –/ “движение вперед”<(1, 1), (1, 2), (2, 3), (3, 3), (4, 4), (4, 5), (5, 4)> <>(конец перебора: некуда идти, некуда возвращаться) /– то же –/ В рассмотренном примере оптимальным оказался путь длиной 9 ходов, проходящий через клетки <(1, 1), (1, 2), (2, 3), (3, 3), 14 (4, 3), (4, 4), (4, 5), (5, 4)>.
Задача о n ферзях • Задача заключается в размещении n ферзей на шахматной доске размером n n так, чтобы никакие два ферзя не угрожали другу, находясь на одной горизонтали, вертикали или диагонали. • Для n = 1 задача имеет тривиальное решение; легко убедиться, что для n= 2 и n = 3 решений не существует. Поэтому начнем с задачи с четырьмя ферзями и решим ее с помощью поиска с возвратом. Поскольку каждый ферзь должен находиться на собственной горизонтали, все, что надо, — это указать вертикаль для каждого ферзя на доске, показанной на рис. 2. • Соответственно, если на очередной горизонтали нельзя разместить ферзя, то задача не решаема. • Рис. 2. Доска для задачи о четырех ферзях 15
Пример задачи с четырьмя ферзями • Начинаем с пустой доски и помещаем ферзя 1 в первую возможную позицию на его горизонтали; это позиция на вертикали 1. • Q Затем мы размещаем ферзя 2 в первую допустимую позицию (после неудачных попыток размещения на вертикалях 1 и 2) на вертикали 3, в квадрате (2, 3). Это тупиковая позиция, поскольку при ней оказывается невозможно разместить третьего ферзя так, чтобы он не был под боем. Соответственно, алгоритм осуществляет возврат к предыдущему состоянию и помещает ферзя в позицию (2, 4). Тогда третий ферзь может быть помещен только в позицию (3, 2), что приводит к очередному тупику. Q Q • Q Q Q Q После этого алгоритм осуществляет возврат к ферзю 1 и помещает его в очередной допустимой позиции (1, 2). Ферзь 2 может быть размещен только в позиции (2, 4), ферзь 3 — только в позиции (3, 1), а ферзь 4 — в позиции (4, 3), что дает решение поставленной задачи. 16
Дерево пространства состояний задачи о четырех ферзях. Крестиками помечены неудачные попытки разместить ферзей на указанных вертикалях. Числа вверху указывают порядок генерации узлов Если требуется найти другие решения поставленной задачи (сколько всего их у задачи о четырех ферзях? ), алгоритм может просто продолжить операции с листа, в котором оказалось найдено 17 решение. В качестве альтернативы можно использовать симметрию шахматной доски.
Усовершенствования алгоритма поиска с возвратом на примере задачи о ферзях • Для обычной шахматной доски (n=8) существует около 4, 4 х109 возможных способов расстановки 8 ферзей. • Возможные упрощения задачи: – каждый столбец содержит самое большее одного ферзя, что дает около 1, 7 х 107 расстановок – никакие два ферзя нельзя поставить в одну строку, что дает около 4, 0 х 104 вариантов. – Тот факт, что никакие два ферзя не могут находиться на одной диагонали, сокращает число вариантов еще больше. – В итоге в дереве поиска остается только 2056 узлов. 18
Два решения можно считать эквивалентными, если одно из них переводится в другое с помощью ряда вращений и/или отражений. • например Q Q Q Основное решение Q Q Q Решение получено путём поворота основного решения вокруг вертикальной оси симметрии Q Решение получено путём поворота основного решения вокруг горизонтальной оси симметрии Q Q Q 19
Другим усовершенствованием является слияние, или склеивание, ветвей. Идея состоит в том, чтобы избежать выполнения дважды одной и той же работы: если два или больше поддеревьев данного дерева изоморфны, мы хотим исследовать лишь одно из них. 20
переупорядочение поиска • • Этот эвристический подход можно использовать несколькими способами. Во-первых, если интуиция подсказывает, что все решения будут иметь некоторый определенный вид, то благоразумно строить поиск так, чтобы раньше других исследовать возможные решения именно этого вида. Во-вторых, если возможно, то дерево (следует перестроить так, чтобы узлы меньшей степени (т. е. имеющие относительно мало сыновей) были бы близки к вершине дерева; например, дерево на рис. 3(а) предпочтительнее, чем дерево, показанное на рис. 3(b). В общем случае, для того чтобы обнаружить, что путь не может ввести к решению, должно быть накоплено несколько ограничений, и обычно это случается на фиксированной глубине дерева. В результате большее число узлов будет запрещено, если большая часть ветвлений будет находиться ближе к листьям, чем к корням. Конечно, нужно понимать, что такой вид перестройки дерева может оказаться бесполезным, если должно быть исследовано все дерево. Более того, даже если не требуется исследовать все дерево, перестройка может переместить решения не ближе к началу поиска, а дальше от него. 21
метод декомпозиции • Суть метода состоит в разложении задачи на k подзадач, решении этих подзадач и затем объединение решений подзадач в решение исходной задачи. • В этом случае требования к объему памяти могут быть очень высокими, поскольку нужно хранить все решения подзадач, однако, скорость может значительно возрасти. • Например, если для решения задачи размера n требуется время с 2 n, то использование метода декомпозиции позволит уменьшить время до величины k c 2 n/k+Т, где Т — время, требуемое для объединения решений подзадач. • Если число решений подзадач мало и объединить их нетрудно, то Т будет относительно малым, и в результате этот метод даст огромную экономию. 22
Анализ усовершенствований • усовершенствования нужно делать не только при анализе задачи перед программированием, но также и во время работы программы. • В задаче о ферзях, например, анализ позволяет нам ввести небольшие ограничения уже при составлении программы, но ограничение, состоящее в том, что ферзи, стоящие на одной диагонали, бьют друга, можно применять только в процессе появления конфигураций, так как для этого ограничения известного анализа нет. 23
Анализ усовершенствований • Аналогично, склеивание и перестановку поиска можно применять в некоторых ситуациях во время работы. Применение склеивания во время работы означает возможность распознать одинаковые поддеревья по частичному решению в корне поддерева. • Использование процедуры перестройки поиска во время работы означает либо то, что делается обоснованное предположение о том, что текущее дерево не предоставляет интереса и поэтому его просмотр надо отложить, либо то, что для частичного решения (α 1, …, αk) остальные компоненты решения ищутся в некотором динамически определяемом порядке вместо обычного порядка αk+1 , αk+2. 24
Оценка сложности поиска с возвращением • Обычно поиск с возвращением приводит к алгоритмам, экспоненциальным по своим параметрам. • Аналитическое выражение для оценки удается получить редко, поскольку трудно предсказать, как взаимодействуют различные ограничения по мере того, как они появляются при продвижении вглубь дерева. 25
Оценка сложности поиска с возвращением • Существует, однако, интересный метод Монте. Карло оценки размеров дерева. Идея состоит в проведении нескольких испытаний, при этом каждое испытание представляет собой проведение поиска с возвращением со случайно выбранными значениями аi в частичном решении (a 1, a 2, . . . , ak-1) • Это вычисление по методу Монте-Карло можно использовать для оценки эффективности алгоритма поиска с возвращением путем сравнения его с эталоном, полученным для задачи с меньшей размерностью. 26
Два способа программирования Вложенные друг в друга циклы – очень жесткая структура и если нам надо решать задачу для 100 ферзей, то нам придется писать 100 вложенных друг в друга циклов. Более того, для каждого n нам придётся писать свой вариант алгоритма, отличающийся количеством вложенных циклов. Поэтому вариант с вложенными циклами обычно бывает неприемлемым для реализации перебора с возвратом. • До сих пор мы представляли алгоритм поиска с возвращением в виде двух вложенных циклов - внутреннего цикла для расширения решения и внешнего цикла для возвращения. Этот же алгоритм можно запрограммировать двумя другими существенно различными способами: один с использованием языка программирования высокого уровня с рекурсией и другой с использованием языка ассемблера со средствами макрорасширения. В последнем случае мы предполагаем, что решениями могут быть только листья дерева. • Рекурсивный подход полезен прежде всего для алгоритмов на графах. • Подход к поиску с возвращением с позиций языка ассемблера основывается на предположении, что наиболее важным аспектом программы является ее быстродействие. Многие приложения процедуры возвращения требуют относительно малой памяти, и поэтому будет разумным значительно расширить требования к памяти для того, чтобы существенно уменьшить требуемое время. Одна идея состоит в применении средств макрорасширения ассемблера для производства высоко специализированных программ, в которых все или некоторые циклы не являются вложенными; такой подход устраняет определенные логические проверки и уменьшает число команд для 27 контроля циклов.
Задача 1. О гамильтоновом цикле гамильтонов цикл – это обход всех узлов связного графа и возвращение в исходный узел без повторений 28
Задача 2. О сумме подмножества • Требуется найти подмножество данного множества S = {s 1, . . . , sn}, состоящего из n натуральных чисел, такое, что сумма его элементов равна заданному натуральному числу d. • Например, для S = {1, 2, 5, 6, 8} и d = 9 имеется два решения — {1, 2, 6} и {1, 8}. • При некоторых данных задача может не иметь решений. 29
Полное дерево пространства состояний алгоритма поиска с возвратом, примененного к экземпляру задачи о сумме подмножества S — {3, 5, 6, 7} и d = 15. Число внутри узла представляет собой сумму элементов, включенных в подмножество, представленное этим узлом. Неравенства под листьями указывают причину прекращения их обработки 30
• Удобно отсортировать элементы множества в возрастающем порядке. Будем считать, что s 1 s 2 … sn • Дерево пространства состояний может быть построено как бинарное дерево, как показано на рис. для экземпляра S = {3, 5, 6, 7} и d = 15. Корень дерева представляет начальную точку, в которой не принято решение ни по одному из элементов множества. Его левый и правый дочерние узлы представляют, соответственно, включение s 2 в искомое подмножество и отсутствие в нем этого элемента. Аналогично, переход влево от узла на первом уровне означает включение s 2 в искомое подмножество, а переход вправо — отсутствие этого элемента в искомом множестве. Таким образом, путь от корня к узлу на i-ом уровне дерева указывает, какие из первых i чисел будут включены в подмножество, представленное этим узлом. • Мы записываем значение s', суммы этих чисел, в узле. Если s' равно d, мы получаем решение поставленной задачи. Мы можем либо сообщить о нем и прекратить работу алгоритма, либо, если надо найти все решения, выполнить очередной возврат к родительскому узлу и продолжить работу. Если s' не равно d, мы можем завершить работу с узлом как с бесперспективным при выполнений любого из двух условий: • s' + si+1 > d (сумма s' слишком велика), • s' + ∑sj < d (сумма s' слишком мала). 31
Задача 3. О маршруте шахматного коня • Дана доска n*n, содержащая n 2 полей (клеток). Конь находится в верхнем левом углу доски. Нужно осуществить обход доски, посещая каждое поле ровно один раз. • При решении этой задачи желательно получить ответ на вопросы: – Существует ли способ решения этой задачи? – Имеется ли решение при произвольном исходном положении коня? 32
Общая схема решения задачи • 1. Выполнять пункты 2 и 3, пока не будет выполнен обход всех полей доски. • 2. С того поля, где конь находится, нужно перейти на любое поле, на котором он еще не был. Перейти к п. 2. • 3. Если такого поля не существует, то вернуться назад на поле, с которого был сделан ход на данное. Перейти к п. 1. 33
Анализ решения • В данной переборной задаче номером хода является номер очередного хода коня i (i = 1, 2, . . . , n 2), а вариантом является выбор поля, на котором конь еще не был и который доступен с данного поля. Таким образом, общая схема алгоритма состоит из выбора очередного хода и выбора подходящего поля, если же подходящее поле не найдено, то возврат хода назад и выбор другого подходящего поля. • Особенностью рекурсивного алгоритма является то, что число рекурсивных обращений велико. Так, на доске 8*8 и начале движения с верхнего левого угла коня оно равно 8251165, вдобавок каждый ход сопряжен с выбором из 8 возможных вариантов. • При размерах доски 5*5, 6*6, 7*7 и 8*8 и начальном положении коня на верхнем левом углу доски маршрут проходит по всем полям доски, а результаты получаются за несколько секунд машинного времени (8839, 248256, 7152672, 8251165 рекурсивных обращений соответственно). • Для размеров доски больше чем 8*8 даже за несколько десятков минут машинного времени найти решение не удалось, что можно объяснить либо "комбинаторным взрывом", либо отсутствием решения по данному алгоритму. 34
эвристический подход для улучшения решения задачи о шахматном коне • Для очередного хода выберем такое поле, в которое можно перейти из минимального числа полей. Так мы оставляем свободными поля, доступные из большего числа полей. Для этого дополнительно к матрице доски используем еще одну матрицу М такого же размера n*n, каждый элемент mi, j которой будет содержать число возможных переходов коня с поля hi, j на другие поля. Первоначальное состояние такой матрицы для доски 8*8 приведено на рис. 2 3 4 4 3 2 3 4 6 6 4 3 4 6 8 8 8 8 6 4 3 4 6 6 4 3 2 3 4 4 3 2 • Так же, как и в предыдущем примере, в элемент hi, j заносится номер хода коня, одновременно соответствующий элемент mi, j обнуляется. Так как поле hi, j теперь стало недоступным для перехода с других полей, то соответственно корректируется и матрица m. • Этот эвристический алгоритм с направленным выбором хода коня превращает предыдущий алгоритм с возвратом, реализованный с применением рекурсии, в алгоритм без возврата и без рекурсии. Он выполняется всего за (m - 1) ходов (m - число полей на доске). 35
Задача 5. Раскраска карты • Имеется географическая карта, на которой расположено n стран. Каждую страну надо раскрасить в один из k цветов так, чтобы соседние страны были раскрашены в разные цвета. • Географическую карту будем задавать в виде матрицы C размером n*n. Элемент Ci, j равен 1, если страны i и j – соседние и равен 0 иначе. • Пространство перебора состоит из наборов (x 1, . . . , xn), xi € {1, . . . , k}. Условие совместимости m-го элемента с предыдущими: если Ci, m=1 (1 ≤ i < m), то xi ≤ xm. • Однако в отличие от задачи о ферзях, в данной задаче перебор можно сократить ещё больше за счёт симметрии решений задачи. Предположим, мы нашли решение задачи. Если мы теперь в этом решении у всех вершин поменяем местами i-ую и j-ую краску, то получившаяся раска тоже будет решением. Из таких симметричных решений нам достаточно найти одно. Таким образом, при выборе краски для очередной страны нам достаточно перебрать все уже используемые краски и всего одну 36 (первую) из новых.
Задача 6. Укладка рюкзака. Стандартная формулировка задачи Из заданных n предметов выбрать такие, чтобы их суммарная стоимость была не менее чем S, а суммарный объём не превосходил V. • Видоизменённая формулировка задачи - требуется выбрать предметы, чтобы стоимость была максимальной. • Условия, которые можно проверять при выборе: • суммарный объём уже выбранных предметов не превосходит V; • суммарная стоимость выбранных предметов и тех, которые мы можем выбрать не меньше S. • Второе условие удобнее переписать в виде: суммарная стоимость не взятых предметов не превосходит стоимости всех предметов минус S. 37
Задача 7. Расстановка знаков • Постановка задачи: • Дано целое число m. Вставить между некоторыми цифрами 1, 2, 3, 4, 5, 6, 7, 8, 9, записанными именно в таком порядке, знаки ``+'' и ``-'' так, чтобы значением получившегося выражение было число m. • Например, если m=122, то подойдёт выражение: 12+34 -5 -6+78+9. • Если расставить знаки требуемым образом невозможно, сообщить об этом. 38
Решение задачи о расстановке знаков. • Основной цикл представим несколькими вложенными циклами – каждый для отдельной позиции знака в строке. Получаем 8 вложенных циклов. Довольно длинно, но более эффективно. Причём рекурсивный вариант этого алгоритма устраняет громоздкость текста: • Цикл, перебирающий три варианта расстановки знаков, проще расписать напрямую. • Осуществим самое важное улучшение алгоритма: не только построение выражения, но и подсчёт результата будем выполнять как можно раньше. • Итак, мы пришли всё к той же схеме перебора с возвратом. Правда в этой задаче не удаётся отсечь варианты на ранних этапах перебора 39
Общие замечания • В заключение следует сделать три замечания по поводу поиска с возвратом. • Во-первых, этот метод обычно применяется для сложных комбинаторных задач, для точного решения которых, возможно, не существует эффективных алгоритмов. • Во-вторых, поиск с возвратом как минимум оставляет надежду на то, что решение некоторых задач нетривиальных размеров будет найдено за приемлемое время. • В-третьих, даже если поиск с возвратом не удаляет ни одного варианта из пространства состояний задачи и в результате генерирует все его варианты, то он все равно обеспечивает особый метод генерации, который может быть ценен сам по себе. 40
Метод ветвей и границ • По сравнению с методом поиска с возвратом метод ветвей и границ требует: – способа получения для каждого узла дерева границу наилучшего значения целевой функции для всех дальнейших решений; – значение наилучшего решения, полученного к этому моменту. • Если такая информация доступна, то мы можем сравнивать значение границы узла со значением наилучшего решения, полученного к этому моменту: если значение границы не лучше значения уже имеющегося наилучшего решения, то эта ветвь обрезается. В этом заключается основная идея метода ветвей и границ. 41
• В общем случае мы завершаем путь поиска в текущем узле дерева по одной из трех следующих причин: – Значение границы узла не лучше значения наилучшего решения, найденного к этому моменту. – Узел не представляет допустимых решений из-за нарушения ограничений, налагаемых задачей. – Подмножество допустимых решений, представляемое узлом, состоит из одного элемента (следовательно, дальнейший выбор невозможен) - в этом случае мы сравниваем значение целевой функции для этого допустимого решения со значением целевой функции наилучшего полученного к настоящему моменту решения и обновляем последнее текущим, если новое решение оказывается лучше. 42
Задача о назначениях • имеется n работников, которым надо выполнить n заданий, и надо найти распределение заданий по работникам с наименьшей общей стоимостью. • Задача о назначениях определяется матрицей С размером n*n, • мы можем сформулировать задачу следующим образом: – выбрать по одному элементу в каждой строке матрицы – никакие два выбранных элемента не располагались в одном столбце, – общая сумма выбранных элементов была минимальной. 43
нижняя граница стоимости • Стоимость любого решения, включая оптимальное, не может быть меньше суммы наименьших элементов в каждой из строк матрицы. Для приведенного примера эта сумма равна 2 + 3 + 1 + 4= 10. 44
нижняя граница стоимости Это значение не является суммой ни одного из допустимых выборов (3 и 1 находятся в одном столбце матрицы), это просто нижняя граница стоимости любого варианта, соответствующего ограничениям задачи. Применяем такие же рассуждения и к частично построенным решениям. Например, для любого допустимого решения, которое выбирает из первой строки 9, нижняя граница равна 9+3+1+4=17 45
О порядке генерации узлов дерева • Вместо генерации одного дочернего узла по отношению к последнему обещающему, как это делалось при поиске с возвратом, мы будем генерировать все дочерние узлы для наиболее обещающего среди незавершенных листьев текущего дерева. • Как можно определить, какие из узлов являются наиболее перспективными? Это можно сделать, сравнивая нижние границы незавершённых листьев. • Разумно рассматривать как наиболее перспективный узел с наилучшей границей, хотя это, конечно, не препятствует тому, что оптимальное решение будет в конечном итоге принадлежать иной ветви дерева пространства состояний. Такая стратегия называется методом ветвей и границ с выбором наилучшего варианта (best-first branch-and-bound). 46
47
48
49
Заключение к задаче • Для данной задачи имеется полиномиальный алгоритм решения под названием Венгерский метод (см. , например, Х. Пападимитриу, К. Стайглиц Комбинаторная оптимизация. Алгоритмы и сложность. Перевод с англ. М. Мир 1985 512 с. ). • В свете наличия такого эффективного алгоритма решение проблемы о назначениях методом ветвей и границ следует рассматривать как учебный пример, а не как практическую рекомендацию. 50
Применение метода ветвей и границ к задаче о рюкзаке • Постановка задачи: дано n предметов с весами w 1, w 2, …, wn, и ценами v 1, v 2, …, vn, а также рюкзак, выдерживающий вес W. Требуется найти подмножество предметов, которое можно разместить в рюкзаке и которое имеет при этом максимальную цену. • Некоторые рекомендации: – удобно упорядочить предметы в убывающем порядке по их удельной цене (отношению цены к весу) v 1/ w 1 ≥v 2/ w 2 ≥, …, ≥vn/ wn с разрешением неоднозначностей произвольным образом: – Естественной структурой дерева пространства состояний для данной задачи является бинарное дерево, построенное следующим образом: ветвь, идущая влево, указывает на включение очередного элемента в подмножество, в то время как правая ветвь указывает на отсутствие элемента в подмножестве. Мы записываем общий вес w и общую стоимость v в соответствующий узел, вместе с верхней границей ub для соответствующего подмножества, которое может быть получено путем добавления некоторых элементов (возможно, никаких) к этому выбору. 51
Пример Мы переупорядочили элементы в порядке убывания их удельных стоимостей. Емкость рюкзака W =10. Простым способом вычисления верхней границы иb является добавление к общей стоимости уже выбранных элементов v произведения оставшейся емкости рюкзака W-w и наибольшего значения удельной стоимости среди оставшихся элементов, которое равно vi+1 / wi+1: иb = v + (W - w) (vi+1 / wi+1) • 52
Дерево пространства состояний алгоритма ветвей и границ для задачи о рюкзаке иb = v + (W - w) (vi+1 / wi+1) 53
Применение метода ветвей и границ к задаче коммивояжера • Мы сможем применить метод ветвей и границ к экземпляру задачи коммивояжера, если найдем подходящий метод оценки нижней границы длины маршрута. • Очень простая нижняя граница может быть получена путем поиска наименьшего элемента в матрице расстояний между городами и умножении его на количество городов n. • Однако имеется менее очевидная и более информативная нижняя граница, не требующая большого количества вычислений. Нетрудно показать, что можно вычислить нижнюю границу длины любого маршрута следующим образом. Для каждого i-го города находим сумму расстояний от города i до двух ближайших городов, после чего вычисляем сумму s этих чисел и делим результат на 2. Если все расстояния — целые числа, округляем результат до ближайшего целого: Lb= s/2 54
а) Взвешенный граф. б) Дерево пространства состояний алгоритма ветвей и границ для данного графа. Список вершин в узле указывает начальную часть гамильтонова цикла, представленного узлом Например, для варианта задачи, показанного на рис. имеем Lb= [(1+3)+(3+6)+(1+2)+(3+4) +(2+3)]/2 =14 Кроме того, для любого подмножества маршрутов, которое должно включать некоторые ребра данного графа, мы можем соответственно изменить 55 нижнюю границу
Некоторые соображения • Использование дополнительной информации, такой как симметрия доски в игре, могут расширить диапазон решаемых экземпляров задач. • В противоположность поиску с возвратом решение задачи методом ветвей и границ включает как необходимость выбора порядка генерации узлов, так и поиска хорошей функции для вычисления границ. • Хотя рассмотренное правило выбора наилучшего варианта представляет собой достаточно разумный подход, оно может и не приводить к решению быстрее, чем другие стратегии. 56
Некоторые соображения • Поиск хорошей функции для вычисления границ — задача обычно непростая. С одной стороны, эта функция должна быть легко вычислимой, с другой, она не может быть слишком упрощенной — в противном случае она не сможет выполнять свою основную задачу отсечения как можно большего количества ветвей дерева пространства состояний. • Поиск компромисса между этими конкурирующими требованиями может потребовать интенсивных экспериментов с широким диапазоном экземпляров рассматриваемой задачи. 57
а- -отсечение • Существенно другой разновидностью метода ветвей и границ является метод, встречающийся при построении деревьев игр. • Дерево игры — это дерево, которое появляется в результате исследования способом поиска с возвращением всевозможных последовательностей ходов: – корень есть начальная конфигурация игры. В частности, если отец узла принадлежит уровню дерева, на котором вычисляется максимум, то значение, присвоенное узлу, есть нижняя граница значения его отца. Такая нижняя граница уровня, в котором вычисляется максимум, называется значением. Cыновья корня — это возможные положения после хода первого игрока; В симметричной ситуации, когда отец находился на уровне, в котором вычисляется минимум, получающаяся верхняя оценка его значения называется значением. – сыновья этих узлов — это возможные положения после ответного хода второго игрока и т. д. 58
Пример фрагменты дерева игры в крестики-нолики Уровень 0 Ход первого игрока Уровень 1 + + + Ход второго игрока Уровень 2 о + + о + о о + + о+ о о + + Ход первого игрока Уровень 3 + + + о + о + + о+ + о + + о + +о о + о+ о + + + 59 о
Динамическое программирование • Динамическим программированием называют процесс пошагового решения задач, когда на каждом шаге выбирается одно решение из множества допустимых на этом шаге решений, оптимизирующее заданную (целевую) функцию F. • Метод динамического программирования применим только тогда, когда функция F удовлетворяет принципу оптимальности Беллмана. Этот принцип требует, чтобы всякий отрезок ai, ai+1, . . . , am оптимальной последовательности а 1, . . . , аn (1< = i < = т< = n) был бы сам оптимальным среди всех отрезков, совпадающих с ним по числу элементов и в крайних элементах. Это свойство позволяет найти оптимальную последовательность, постепенно удлиняя уже найденные от начала (конца) последовательности отрезки. • Применение этого принципа к решению комбинаторных задач по существу означает использование принципа декомпозиции: вначале находятся решения подзадач, затем они используются для отыскания решения больших подзадач и, наконец, для решения самой задачи. 60
Когда применимо динамическое программирование Два признака, характерных для задач, решаемых методом динамического программирования. • • Оптимальность для подзадач Перекрывающиеся подзадачи 61
Оптимальность для подзадач • Необходимо сначала описать структуру оптимального решения. Задача обладает свойством оптимальности для подзадач, если оптимальное решение задачи содержит оптимальные решения её подзадач. Если задача обладает этим свойством, то динамическое программирование может оказаться полезным для её решения (возможно, применим и жадный алгоритм). • Как только свойство оптимальности для подзадач установлено, обычно становится ясно, с каким именно множеством подзадач будет иметь дело алгоритм. Например, для задачи о перемножении последовательности матриц подзадачами будут задачи о перемножении кусков этой последовательности. 62
Перекрывающиеся подзадачи • второе свойство задач существенное при использовании динамического программирования, — небольшое число различных подзадач. • Благодаря этому при рекурсивном решении задачи мы многократно выходим на одни и те же подзадачи. В таком случае говорят, что у оптимизационной задачи имеются перекрывающиеся подзадачи. • Обычно количество подзадач полиномиально зависит от размера исходных данных. 63
Алгоритм, основанный на динамическом программировании • 1) описать строение оптимальных решений, • 2) выписать рекуррентное соотношение, связывающее оптимальные значения параметра для подзадач, • 3) двигаясь снизу вверх, вычислить оптимальное значение параметра для подзадач, • 4) пользуясь полученной информацией, построить оптимальное решение. • Основную часть работы составляют шаги 1 -3. Если нас интересует только оптимальное значение параметра, шаг 4 не нужен. Если же шаг 4 необходим, для построения оптимального решения иногда приходится получать и хранить дополнительную информацию в процессе выполнения шага 3. 64
Пример применения динамического программирования Перемножение нескольких матриц • Задача об умножении последовательности матриц может быть сформулирована следующим образом: дана последовательность из n матриц A 1 A 2 … An заданных размеров (матрица Ai имеет размер pi-1 pi ); требуется найти такую расстановку скобок в произведении A 1 A 2 …An, чтобы вычисление произведения требовало наименьшего числа умножений. • конечный результат вычислений не зависит от расстановки скобок, но способ расстановки скобок может сильно повлиять на стоимость перемножения матриц. • Матрицы А и В можно перемножать, только если число столбцов у А равно числу строк у В. 65
Некоторые замечания к примеру о перемножении матриц • Прежде чем применять динамическое программирование к задаче об умножении последовательности матриц, стоит убедиться, что простой перебор всех возможных расстановок скобок не даст эффективного алгоритма. • Чтобы понять, что число вариантов экспоненциально, разобьём все матрицы на группы по три; произведение для каждой группы можно вычислить двумя способами, так что для 3 n матриц есть не менее 2 n вариантов. • Например, рассмотрим последовательность из трех матриц (A 1, A 2, A 3) размеров 10 х 100, 100 х 5 и 5 х 50 соответственно. При вычислении ((A 1 A 2)A 3) нужно 10 • 100 • 5 = 5000 умножений, чтобы найти матрицу A 1 A 2, а затем 10 • 50 = 2500 умножений, чтобы умножить эту матрицу на А 3. . Всего 7500 умножений. При расстановке скобок (A 1(A 2 A 3)) мы делаем 100 х 50 = 25000 умножений для нахождения матрицы A 2 A 3, , плюс ещё 10 х 100 х 50 = 50000 умножений (умножение A 1 на A 2 A 3), итого 75 000 66 умножений. Тем самым, первый способ расстановки скобок в 10 раз выгоднее.
Шаг 1: построение оптимальной расстановки скобок • При вычислении произведения, диктуемом оптимальной расстановкой скобок, мы сначала вычисляем произведения A 1. . . k и Ak+1…n , для некоторого k, удовлетворяющего неравенству 1≤k n, а затем перемножаем их и получаем окончательный ответ A 1. . n. Стоимость этой оптимальной расстановки равна стоимости вычисления матрицы A 1…k плюс стоимость вычисления матрицы Ak+1…n плюс стоимость перемножения этих двух матриц. • Чем меньше умножений нам потребуется для вычисления A 1. . . k и Ak+1…n , тем меньше будет общее число умножений. Стало быть, оптимальное решение задачи о перемножении последовательности матриц содержит оптимальные решения задач о перемножении её частей. Это позволяет применить динамическое программирование. 67
Шаг 2: рекуррентное соотношение • • • Cтоимость оптимального решения задачи выразить через стоимости оптимальных решений её подзадач. Такими подзадачами будут задачи об оптимальной расстановке скобок в произведениях Aij= Ai. Ai+1… Aj для 1≤i ≤j ≤n. Обозначим через m[i, j] минимальное количество умножений, необходимое для вычисления матрицы Ai…j; в частности, стоимость вычисления всего произведения А 1…n есть m[1, n]. Числа m[i, j] можно вычислить так. Если i = j, то последовательность состоит из одной матрицы Ai. . i = Ai и умножения вообще не нужны. Стало быть, m[i, i] = 0 для i = 1, 2, . . . , п. Чтобы подсчитать т[i, j] для i < j, мы воспользуемся информацией о строении оптимального решения, полученной на шаге 1. Пусть при оптимальной расстановке скобок в произведении Ai Ai+1 • …. • Aj последним идет умножение Ai • … • Ak на Ak+1 • . . . • Aj, где i k < j. Тогда m[i, j] равно сумме минимальных стоимостей вычисления произведений Ai…k и Ak+1. . j плюс стоимость перемножения этих двух матриц. Поскольку для вычисления произведения Ai. . k Ak+1…j требуется pi-1 pkpj умножений, m[i, j] = m [i, k] + m[k+1, j]+pi-1 pkpj В этом соотношении подразумевается, что оптимальное значение k; нам известно; на деле это не так. Однако число k может принимать всего лишь j —i различных значений: i, i+1, …, j-1. Поскольку одно из них оптимально, достаточно перебрать эти значения k и выбрать наилучшее. Получаем рекуррентную формулу: m[i, j] =0 при i=j m[i, j] = min{m [i, k] + m[k+1, j]+pi-1 pkpj } при i
Шаг 3: вычисление оптимальной стоимости • Пользуясь полученным рекуррентным соотношением легко написать рекурсивный алгоритм, определяющий минимальную стоимость вычисления произведения A 1 A 2 • . . . • An (т. е. число m[1, n]). • Однако время работы такого алгоритма экспоненциально зависит от n, так что этот алгоритм не лучше полного перебора. • Настоящий выигрыш во времени мы получим, если воспользуемся тем, что подзадач относительно немного: по одной задаче для каждой пары (i, j), для которой 1 i j n, а всего Cn 2 + n = (n 2). • Экспоненциальное время работы возникает потому, рекурсивный алгоритм решает каждую из подзадач по многу раз, на разных ветвях дерева рекурсии. Такое “перекрытие подзадач” — характерный признак задач, решаемых методом динамического программирования. 69
Шаг 4: построение оптимального решения • Предыдущий шаг находит минимальное число умножений, необходимое для перемножения последовательности матриц. Осталось найти расстановку скобок, приводящую к такому числу умножений. • Для этого мы используем таблицу s[1. . n, 1. . n]. В клетке s[1, n] записано место последнего умножения при оптимальной расстановке скобок; • Предшествующие умножения можно найти рекурсивно 70
Подведём итоги: задача об оптимальном порядке умножения n матриц • Задача может быть решена за время О(n 3) либо “сверху вниз” (рекурсивный алгоритм с запоминанием ответов), либо “снизу вверх” (динамическое программирование). Оба алгоритма основаны на перекрытии подзадач; число подзадач есть (n 2), и оба алгоритма решают каждую из подзадач лишь единожды. • Вообще говоря, если каждая из подзадач должна быть решена хоть раз, метод динамического программирования (“снизу вверх”) обычно эффективнее, чем рекурсия с запоминанием ответов, поскольку реализация рекурсии (а также проверка, есть ответ в таблице или ещё нет) требует дополнительного времени. Но если для нахождения оптимума не обязательно решать все подзадачи, подход “сверху вниз” имеет то преимущество, что решаются лишь те подзадачи, которые действительно нужны. 71
Построение наибольшей общей подпоследовательности (НОП) • Если решать задачу о НОП “в лоб”, перебирая все подпоследовательности X и проверяя для каждой из них, не будет ли она подпоследовательностью последовательности У, то алгоритм будет работать экспоненциальное время, поскольку последовательность длины т имеет 2 m подпоследовательностей 72
Оптимальная триангуляция многоугольника • • Триангуляция (triangulation) многоугольника — это набор диагоналей, разрезающих многоугольник на треугольники; сторонами этих треугольников являются стороны исходного многоугольника и диагонали триангуляции. (Триангуляцию можно также определить как максимальное множество диагоналей, не пересекающих друга. ) Задача об оптимальной триангуляции (optimal triangulation problem) состоит в следующем. Дан выпуклый многоугольник Р = v 0, v 1, …, vn-1 и весовая функция w, определённая на множестве треугольников с вершинами в вершинах Р. Требуется найти триангуляцию, для которой сумма весов треугольников будет наименьшей. 73
Заключение к динамическому программированию • Систематическое изучение динамического программирования было начато Р. Беллманом в 1955 году [21], хотя некоторые приёмы такого рода были известны и ранее. Кстати, слово “программирование” (programming) в словосочетаниях “динамическое программирование” (dynamic programming), а также “линейное программирование” (linear programming) не означает составление программ для компьютера. • Ху и Шинг [106] придумали работающий за время O(nlogn) алгоритм для задачи о порядке перемножения матриц; они же указали соответствие между этой задачей и задачей об оптимальной триангуляции. • Кнут поставил вопрос, возможен ли для этой задачи субквадратичный алгоритм. Масек и Патерсон [143] показали, что возможен, найдя алгоритм, работающий за время O(mn/logn) при n т и фиксированном размере множества, из которого берутся члены последовательностей. Для случая, когда в последовательностях нет повторений, алгоритм с оценкой О((n + m)log(n + m)) построен в статье Шимански [184]. Многие из этих результатов обобщаются на задачу о стоимости редактирования 74
Задачи, решаемые с помощью динамического программирования 75
Разбиение абзаца на строки • Абзац текста состоит из n слов длиной l 1, l 2, …, ln (длина слова — число символов в нём). Считая, что все символы имеют равную ширину (как на пишущей машинке), мы хотим оптимальным образом разбить его на строки длиной не более М символов. Оптимальность при этом определяется так: посчитаем число “лишних” пробелов в каждой строке (то есть посмотрим, на сколько длина строки меньше М, если между словами ставить по одному пробелу) и сложим кубы этих чисел для всех строк, кроме последней: чем больше эта сумма, тем хуже абзац. Используя динамическое программирование, разработайте алгоритм оптимального разбиения абзаца на строки; оцените время его работы и требуемый объём памяти. 76
Стоимость редактирования • Мы хотим преобразовать строку символов х[1. . т] в новую строку у[1. . n] с помощью следующих операций: • перенос символа из исходной строки в новую, • перенос двух соседних символов из исходной строки в новую с одновременной их перестановкой (“транспозиция”), • добавление символа (справа) к новой строке, • удаление первого символа из старой строки, • замена (удаление символа из исходной строки и добавление другого символа в новую строку), 77 • наконец, удаление остатка старой строки.
Вечеринка в фирме • Профессору поручено устроить вечеринку в фирме “ТОО КЛМН”. Структура фирмы иерархична: отношение подчинённости задано деревом, корень которого — директор. Отдел кадров знает рейтинг каждого сотрудника (действительное число). Чтобы всем было весело, директор распорядился, чтобы никто не оказался на вечеринке вместе со своим непосредственным начальником. • а. Разработайте алгоритм, составляющий список приглашённых с наибольшим суммарным рейтингом. • б. Та же задача с дополнительным ограничением: директор должен быть в списке приглашённых. 78
Алгоритм Витерби • Динамическое программирование может быть применено к задаче распознавания речи. В качестве модели рассмотрим ориентированный граф G = (V, Е) и отображение о, сопоставляющее с каждым ребром (u, v) звук (и, v) из множества возможных звуков . В графе выделена некоторая вершина v 0. Каждому пути, начинающемуся в v 0 , соответствует последовательность звуков (элементов ). 79
МЕТОДЫ РЕШЕТА • решето представляет собой метод, который рассматривает конечное множество и исключает все элементы этого множества, не представляющие интереса. Этот метод является логическим дополнением к процессу поиска с возвращением, который перечисляет все элементы множества, представляющие интерес. • Методы решета полезны прежде всего в теоретико-числовых вычислениях. Например, одним из наиболее известных методов отыскания простых чисел является «решето Эратосфена» . Это решето перечисляет составные (не простые) числа между N и N 2 для некоторого N • Легко понять, почему методы решета могут быть полезны. Если в множестве возможных решений элементы можно удобно занумеровать натуральными числами, то хранить нужно только характеристический вектор; в этом векторе i-й разряд равен нулю, если i-й элемент не является решением, и равен единице в противном случае. Таким образом, на множествах, состоящих буквально из миллионов элементов, возможен поиск без явного порождения и исследования каждого элемента множества. Кроме того, в большинстве вычислительных устройств булевы операции можно производить параллельно над многими разрядами, обеспечивая тем самым значительную экономию времени. 80
Разновидности метода решета • • • решето Эратосфена Нерекурсивное модульное решето обобщенное модульное решето Рекурсивное решето Двойное решето Решето, отбраковывающее изоморфные объекты 81
ПРИБЛИЖЕНИЯ ИСЧЕРПЫВАЮЩЕГО ПОИСКА • • исследуем эвристические алгоритмы для задачи коммивояжера. В случае n городов эти алгоритмы требуют времени лишь О (n 2), и можно показать, что они дают маршруты, стоимость которых не слишком отличается от стоимости оптимального маршрута, если матрица стоимостей симметрична и удовлетворяет неравенству треугольника. Такие приближенные алгоритмы имеют большую практическую ценность для задач, в которых время, необходимое для отыскания оптимального результата, растет быстро при увеличении размера задачи. Типичным эвристическим методом в задачах оптимизации является поиск решений, которые в некотором смысле оптимальны локально, а не глобально. например, очевидный метод ближайшего соседа построения маршрута по n городам. В качестве начальной точки произвольно выбираем один из городов. Среди всех еще не посещавшихся городов в качестве следующего выбираем ближайший к только что выбранному (т. е. последнему городу, добавленному к маршруту); если все города уже посещались, возвращаемся в начальный город. В этом случае условием локальной оптимальности является то, что выбираемый на каждом шаге город является ближайшим к последнему пройденному. Это условие не обязательно является условием глобальной оптимальности, поскольку небольшое отклонение в начале пути может дать существенную экономию позже. Алгоритм ближайшего соседа можно легко реализовать за время, пропорциональное n 2 82
Приближенные алгоритмы для задачи о рюкзаке • известная NP-сложная задача — задача о рюкзаке, с которой мы познакомились ранее. Дано n предметов с весами и ценами, а также рюкзак, выдерживающий вес W. Наша задача — найти подмножество предметов, которое можно разместить в рюкзаке и которое имеет при этом максимальную цену. Мы видели, как можно решить эту задачу методом перебора с возвратом, динамического программирования и ветвей и границ. Теперь решим эту задачу при помощи приближенных алгоритмов. 83
Жадные алгоритмы для задачи о рюкзаке • Вот как выглядит алгоритм, основанный на этой жадной эвристике. • Шаг 1. Вычислим удельные стоимости всех предметов множества ri= vi /wi , i = 1, 2, . . . , n. • Шаг 2. Отсортируем предметы в невозрастающем порядке по их удельным стоимостям, вычисленным на шаге 1 (неоднозначности разрешаются произвольным образом). • Шаг 3. До тех пор пока в отсортированном списке не останется ни одного предмета, повторяем следующие действия: если текущий предмет помещается в рюкзак, мы помещаем его туда; в противном случае переходим к следующему предмету. 84
α- β-отсечение ≥ 3 максимум ≤ 3 m 3 >5 d a b c 1 3 0 e <2 z >4 h f g i 2 q l j k 2 5 3 4 2 2 β-отсечение u n o p 1 0 минимум максимум y 2 r s 5 6 t v w x 4 3 5 α-отсечение 2 85


