Пред.
След.
Макеты страниц
Распознанный текст, спецсимволы и формулы могут содержать ошибки, поэтому с корректным вариантом рекомендуем ознакомиться на отсканированных изображениях учебника выше Также, советуем воспользоваться поиском по сайту, мы уверены, что вы сможете найти больше информации по нужной Вам тематике ДЛЯ СТУДЕНТОВ И ШКОЛЬНИКОВ ЕСТЬ
ZADANIA.TO
Глава 4. КЛАССИЧЕСКИЕ МЕТОДЫ РЕШЕНИЯ ЗАДАЧВведениеСуществуют четыре основных способа решения какой-либо задачи: 1. Применение явной формулы. 2. Использование рекурсивного определения. 3. Использование алгоритма. 4. Метод перебора, метод проб и ошибок и др. Несомненно, первый способ является “наилучшим”: мы используем найденную и доказанную ранее формулу, которая во всех случаях дает решение поставленной задачи. К подобному “лобовому” подходу сводится решение таких задач, как определение нулей квадратного уравнения, определение названия дня, соответствующего произвольной дате, определение силы тока в заданной электрической схеме. Собственно задача математики и состоит в том, чтобы найти явные формулы для решения как можно большего числа возможных задач. Если такая формула существует, сложность задачи оказывается связанной с эффективностью вычислений. По определению в формулу может входить только конечное число символов и операций, и это верно для любого числа параметров, включенных в эту формулу, т. е. для любой размерности 4.1. Примеры хороших алгоритмовПример 1. Подсчитайте сумму Вы знаете соответствующую явную формулу, обладающую постоянной сложностью: в ней используется одна операция сложения, одна операция умножения и одна операция деления:
Пример 2. Подсчитайте сумму квадратов Возможно, вы знаете и умеете доказывать, что
Пример 3. Подсчитайте сумму кубов Вы чувствуете, что перечень примеров можно продолжить... Но здесь у математики эстафету принимает информатика. Если только мы умеем определять конечный процесс вычислений, позволяющий прийти к решению, нас не испугает отсутствие эффективной формулы. В связи с заменой формулы на процесс возникает новый вопрос: через сколько этапов мы получим решение? Ответ на этот вопрос составляет цель данной главы. Часто, исходя из условия задачи, мы располагаем неявной формулой подсчета, в которой решение определяется рекурсивно, постепенно. Так, сумма
т. е. она описывается как процесс, легко представимый в хорошем языке программирования: (см. скан) Чтобы подсчитать
Следующий вызов процедуры разворачивает подсчет
и так далее вплоть до
При этом вызове процедуры, наконец, (см. скан) В обоих случаях сложность вычислений составляет Отсюда следует, что для решения тех задач, для которых неизвестны эффективные явные формулы, необходимо уметь строить алгоритмы приемлемой сложности. В частности, классическим и довольно удобным способом является использование с самого начала рекурсивной записи, которую часто легко осуществить и которая всегда кратка и элегантна. Если же сложность соответствующего алгоритма слишком велика, информа-Хик должен последовательно, исходя из рекурсивной формулы, находить все более явные формулы и так до тех пор, пока не будет получен алгоритм вполне приемлемой сложности. Замечание. Теоретическая сложность, о которой здесь идет речь, подтверждается совершенно реальной сложностью, ощущаемой человеком, работающим за терминалом. Так что усилия информатиков-теоретиков по понижению сложности алгоритмов решения некоторых распространенных задач вполне обоснованны. Пример 4. Предположим, что мы хотим узнать 30-е число Фибоначчи. Это число определяется как формул
Числа Фибоначчи, введенные Леонардом Пизанским, сыном Боначчи (1540 г.), входят в описания некоторых процессов, происходящих в природе (например, процесса воспроизводства населения; число Явная формула. Формальное решение и подсчет общего члена последовательности путем поиска линейной комбинации решений в виде
Но мы можем не знать этого подсчета. Кроме того, эта формула относительно сложная. Для того чтобы убедиться в этом, достаточно подсчитать вручную Теперь рассмотрим два других подхода. Рекурсивная форма. Для этой четко сформулированной задачи рекурсивное программирование является решением с непосредственной подстановкой: (см. скан) Но опять-таки, как и в первом решении, возникает одна сложность. Подобно тому как мы делали это при подсчете суммы чисел натурального ряда, смоделируем развертывание рекурсивного алгоритма в информационной системе. Начало построения стека для подсчета
И так — вплоть до достижения одного из двух явно заданных результатов:
В этом конце стека удается осуществить успешные подстановки, и тогда система возвращается... к Итеративные алгоритмы. Чтобы уменьшить эту дорогостоящую из-за большой глубины рекурсивность и избежать многократного повторения одних и тех же расчетов, можно преобразовать приведенную выше рекурсивную схему в рекуррентную. Иными словами, мы расчленим задачу, предположив, что она решена до определенной точки, т. е. до некоторого значения одного значения Если
Тем самым мы упростили гипотезу рекуррентности и нашу схему подсчета. Итак, у нас есть искомый итеративный алгоритм. Оказывается, нам не нужно было запоминать вектор
Начальные условия и тест остановки программ уже были указаны, так что полный алгоритм рассматриваемого третьего типа записывается следующим образом: (см. скан) Очевидно, что этот алгоритм имеет сложность порядка Разработка алгоритма не всегда столь проста: часто приходится манипулировать более сложными структурами, чем числа или обычные арифметические выражения. В следующем разделе рассмотренный выше, принцип развивается на более сложных примерах, для которых в конце концов удается получить полиномиальный алгоритм. Затем мы составим полный список “хорошо решаемых” на сегодняшний день задач. Однако для некоторых задач, по-видимому, невозможно найти хорошие алгоритмы. Этой проблеме посвящен разд. 4.4. Пример 5. Произведите сортировку В качестве чисел возьмем, например, регистрационные номера или индексы каталога. Операция сортировки неупорядоченных элементов чрезвычайно распространена в информатике. Сначала теоретически установим нижнюю границу сложности этой задачи. Разумеется, никакой явной формулы в привычном смысле этого слова здесь нет. Необходимо определить эффективный процесс упорядочения При этом Оказывается, что
Если перейти к логарифмам и использовать формулу Стурлинга, по которой
Следовательно, чтобы рассортировать множество из Теперь рассмотрим, как действует элементарный алгоритм сортировки.
Рис. 4.1. Дерево тестов для сортировки массива. При сортировке массива первой приходит мысль выбрать наибольший элемент, поместить его в начало и затем проделать то же самое для оставшегося массива, т. е. действовать по схеме: (см. скан) Внутренний цикл дает Однако этот метод можно улучшить. В приведенном алгоритме мы каждый раз теряем информацию, “забывая” результаты тестов сравнения, полученные на предыдущем этапе.
Рис. 4.2. Пример сортировки первого типа. Сэкономить на количестве сравнений можно за • счет замены цикла “повторить для Таким образом мы, с одной стороны, уменьшаем число тестов, необходимых для нахождения максимального элемента, а с другой, получаем сведения, нужные для продолжения поисков. Теперь высота дерева составляет (В действительности для реализации этой сортировки на компьютере надо уточнить способ управления деревом, запоминающим числа, и способ осуществления обменов между рассортированными и нерассортированными элементами. Поскольку сначала дерево не задано, все это имеет значение. К дереву мы приходим постепенно, проходя через стадию “упаковки” - структуры, в которой во всех вершинах, подчиненных некоторому узлу, стоят числа, не превышающие число, расположенное в данном узле.)
Рис. 4.3. Пример сортировки второго типа. Как бы то ни было, мы имеем, таким образом, пример нетривиальной задачи, для которой можно представить оптимальный полиномиальный алгоритм. Пример 6. С задачей найти кратчайший путь из одной точки в другую мы сталкиваемся в жизни ежедневно: путешествуя на автомобиле, в метро, а также при решении некоторых математических головоломок. Возьмем в качестве примера граф, изображенный на рис. 4.4; требуется попасть из точки 1 в точку 6 по такому пути, чтобы сумма расстояний, указанных на каждом ребре, была минимальной. Обычно говорят не о расстояниях между вершинами, а о стоимости ребер. По интуитивным соображениям полный перебор всех возможных путей, ведущих из начальной вершины, в конечную, бесполезен. В самом деле, очевидно, что следует ограничиться только элементарными путями, т. е. путями, которые проходят через каждое ребро графа не более одного раза (при условии, что стоимости положительны). Кроме того, естественно использовать итеративный процесс распространения минимальных путей, начиная с вершины 1. Начав с вершин, соседних с вершиной 1, т. е. связанных с ней только одним ребром, мы будем постепенно подсчитывать эти пути так, чтобы в любой заданный момент времени для любой заданной вершины мы были уверены, что минимальное расстояние до вершины 1 известно точно и возвращаться назад не придется. Иначе говоря, на каждом этапе множество вершин разделено на два подмножества • для каждой вершины из • для каждой вершины из
Рис. 4.4. Задача нахождения кратчайшего пути.
Рис. 4.5. Доказательство алгоритма: путь Вначале множество Чтобы построить полный алгоритм, уточним и систематизируем приведенные рассуждения для графа с произвольными положительными стоимостями. Обозначим
где 3) D является минимальным известным расстоянием от вершины 1 до вершины Итак, вначале Теперь мы, сохраняя введенные обозначения, обобщим представленную выше (для вершин 2 и 3) аргументацию и сформулируем следующее утверждение. Утверждение. Пусть Тогда Таким образом, для Чтобы доказать это свойство, нам нужно доказать, что не существует более короткого пути из 1 в Рассмотрим путь Общая длина (см. скан) Теперь развернем этот алгоритм на примере графа, приведенного на рис. 4.4. • Инициализация:
• Итерация
• Итерация
• Итерация
• Итерация
• Итерация Кратчайшему пути из вершины 1 в вершину 6 соответствует суммарная стоимость 10. Можно заметить, что в приведенном алгоритме порядок перехода вершин из Кроме того, если множество Хотя мы рассматривали пример, в котором связи между вершинами, называемые ребрами, могут проходиться в обоих направлениях, иногда ситуация навязывает однонаправленность прохождения; такой граф называется ориентированным. Направление прохождения связи обозначается в этом случае стрелкой, а ориентированная связь называется дугой. Все выводы, нолученные выше, остаются в силе, поскольку направленность прохождения связи в рассуждениях не участвовала; достаточно определить Если дуга Пример 7. Задача упорядочения. В мастерской по сборке автомобилей работа разбита на определенное число операций известной длительности. Эти операции должны следовать друг за другом во времени с учетом отношений логического следования, которые обусловлены физическими условиями. Информация, которой мы располагаем, сведена в табл. 4.1. Таблица 4.1 (см. скан) Какова минимальная длительность сборки, если предположить, что в нашем распоряжении имеется квалифицированная рабочая сила, способная обеспечить параллельное выполнение операций там, где это возможно? Для ответа на поставленный вопрос мы обозначим каждую операцию точкой и проведем между точками связи, соответствующие отношениям следования. Мы получим таким образом граф, причем на этот раз ориентированный (поскольку отношение Из этого графа видно, что по построению со следует за операциями поставленной задачи. Условия, связанные с отношениями логического следования (такие, как
Рис. 4.6. Ориентированный граф для задачи упорядочения. Найти минимальную длительность сборки означает то же самое, что определить на графе с заданными стоимостями, соответствующими продолжительности операций, путь от вершины а до вершины Отметим, что, поскольку стоимости здесь по-прежнему положительны, а мы ищем максимум, то искомый путь мог бы оказаться бесконечным. Действительно это было бы так, если бы существовало подмножество дуг, такое, что
т. е. подмножество вершин, где мы могли бы ходить по кругу неопределенно долго. Такое подмножество вершин в теории графов называется циклом. Однако подобная ситуация в рассматриваемой задаче упорядочения невозможна: в самом деле, тогда получилось бы, что операция Если учесть отсутствие циклов, рассмотренный в предыдущем разделе алгоритм можно улучшить. Поиск максимума, а не минимума, роли не играет. Мы снова ограничимся элементарными путями (т. е. будем брать каждую дугу не более одного раза). Основная идея остается прежней: вес соотношения вида
пока он не перестанет меняться. Однако при специальном выборе порядка вершин можно свести процедуру к одному этапу Для графа, приведенного на рис. 4.6, максимальное расстояние от а до А и В известно. Если мы знаем расстояние до В, то нам в свою очередь известны максимальные расстояния от а до С, D и Н. Сравнивая Свойство. Ациклический граф обладает по крайней мере одной вершиной, которой не предшествует никакая другая вершина; такая вершина называется корнем. В самом деле, предположим, что это не так, и отметим какую-нибудь вершину. По предположению Данное свойство, позволяющее запустить алгоритм, мы будем использовать неоднократно: действительно, достаточно исключить из множества дуг Теорема. Граф Другими словами, с помощью взаимно однозначного отображения Во-первых, очевидно, что, если мы не сможем построить подобного отображения, поскольку в противном случае, согласно предположению, имело бы
Рис. 4.7. Перестроенный граф для задачи упорядочения. место соотношение:
что вообще невозможно. И наоборот, если граф Если бы в какой-нибудь момент существовала некоторая дуга Алгоритм построения функции классификации вершинВ этом алгоритме каждая дуга из множества Инициализация:
Построение: (см. скан) Первый пласт, несомненно, а, второй—А, третий — В; дуги Замечание. Когда перед глазами имеется рисунок, нумерация не является обязательной; поэтому на рис. 4.7 мы ее опустили. Теперь мы получаем: Затем:
Таким образом, длина максимального пути на графе для задачи упорядочения (рис. 4.6) составляет 16 единиц. Чтобы обнаружить путь, во время каждой итерации мы отмечаем предшествующую вершину, которая дала реальный максимум при подсчете Использованный нами метод известен под названием метода потенциалов-, он был введен Бернардом Роем в 1960 г. Более распространенный, но более трудоемкий американский вариант метода для решения этой задачи называется методом PERT (Program Evaluation and Review Technique); он был разработан в NASA и в RAND в 1954 г. Эти методы постоянно используются для реального решения конкретных задач, главным образом в строительной индустрии, а также в различных отраслях машиностроения (в автомобилестроении, кораблестроении и самолетостроении). Помимо вычисления минимального срока выполнения проекта, эти методы позволяют получить список так называемых “критических” операций, т. е. операций, лежащих (при графическом представлении) на самом длинном из возможных путей. По определению всякое увеличение длительности любой из критических операций обязательно отразится на сроках поставок. Другим полезным следствием нашего алгоритма является информация о распределении в процессе сборки объема работ, выполняемых представителями различных профессий. В перестроенном таким образом графе для определения максимального пути мы располагаем следующим тривиальным алгоритмом: (см. скан) Действительно, новые численные обозначения таковы, что Для каждого отдельного значения итерация требует Нумерация
Наконец, поскольку в этом классе задач данные никогда не известны точно, для отслеживания критического пути и общей длительности в случае, когда длительности операций параметризованы и колеблются в заданных интервалах по известным вероятностным законам, были разработаны вспомогательные способы подсчета. Подробное рассмотрение всех этих способов не входит в задачи данной главы. Здесь мы хотели показать на конкретных примерах суть алгоритмических действий: анализ задачи с целью ее перевода в сжатую и удобную форму (граф); изучение в выбранном ограниченном пространстве новой задачи и проверку на каком-нибудь примере метода, основанного на простых идеях; обобщение, а затем оформление и доказательство алгоритма.
Рис. 4.8. Семь мостов через Преголю: задача об эйлеровом цикле. Пример 8. Топологическая задача Рассмотрим знаменитую задачу об “эйлеровом цикле” на графе. Она состоит в том, чтобы узнать, существует ли на графе определенного вида (таком, как изображен на рис. 4.8) цикл, который проходит по каждому ребру только один раз и возвращается в исходную точку. Разумеется, необходимым условием является связанность графа, т. е. существование цепочки ребер, позволяющей пройти Из одной произвольно взятой точки графа в другую. Еще одно Необходимое условие касается числа ребер, привязанных к каждой вершине: поскольку мы не можем дважды пройти по одному и тому же ребру, нужно, чтобы всякому входу соответствовал выход. Чтобы в связанном графе существовал эйлеров цикл, в нем не должно быть вершин нечетной степени (степень — число ребер, выходящих из данной вершины). Как мы докажем ниже, это условие фактически является достаточным. Для ответа на вопрос о существовании эйлерова цикла это условие предлагает полиномиальный алгоритм, и. кроме того, для реального построения этого цикла в случае его существования оно дает алгоритм, совпадающий по порядку сложности с числом ребер на входе. Необходимое условие. Оно является очевидным. Поскольку цепочка, проходящая через все ребра, входит в каждую вершину и выходит из нее, то для возвращения в исходную вершину нужно, чтобы все лежащие на нашем пути вершины имели четное число ребер. Достаточное условие. Оно является менее очевидным. Мы будем рассуждать по индукции для В соответствии с нашим предположением составим последовательно цепочку Ф, выходящую из произвольной вершины Если мы не можем продолжить цепочку Ф, это означает, что мы вернулись в Обозначим эти компоненты связности через Поскольку с самого начала предполагалось, что граф Так как при любом • цепочку Ф от вершины • эйлеров цикл • цепочку Ф от вершины Проверить приведенные необходимые и достаточные условия в каждой вершине нетрудно, причем суммарная сложность составляет (см. скан) Теперь легко записать полный алгоритм получения эйлерова цикла. Следуя доказательству теоремы, мы будем строить цепочку, постепенно ее дополняя: (см. скан) В этом алгоритме процедура Эйлера по порядку величины с числом ребер исходного графа, т. е. составляет О (т.). Итак, мы имеем прекрасный линейный алгоритм решения задачи Эйлера. Замечание. Ниже мы рассмотрим задачу, близкую задаче Эйлера. Эту задачу изучал Гамильтон, и в его честь она получила название задачи Гамильтона; она состоит в поиске на произвольном графе цикла, проходящего на этот раз не через все ребра, а через все вершины (гл. 5, задача о коммивояжере). Оказывается, что эта новая задача вовсе не относится к тому же классу, что и предыдущая. Многие математики, в течение нескольких веков занимавшиеся задачей Гамильтона, так и не смогли построить для нее, как это удалось сделать для задачи Эйлера, хороший (т. е. полиномиальный) алгоритм. Другими словами, мы не умеем решать обобщенную задачу определения цикла, проходящего через все вершины графа.
|
1 |
Оглавление
|