Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Различные авторы Весь текст 991.22 Kb

Программирование в теоремах и задачах

Предыдущая страница Следующая страница
1 ... 64 65 66 67 68 69 70  71 72 73 74 75 76 77 ... 85
ральными аргументами и значениями определяется соотношениями
        f(0) = a,
        f(x) = h(x, f(l(x)), f(r(x))),
где a - некоторое число, а l, r и h - известные функции. Предпо-
лагается, что если взять произвольное число и начать применять к
нему функции l и r в произвольном порядке, то  рано  или  поздно
получится 0.

     8.3.2. Написать нерекурсивную программу вычисления f.

     Решение. Можно было бы сначала построить дерево, у которого
в корне находится x, а в сыновьях вершины i стоят l(i) и r(i)  -
если только i не равно нулю, а затем вычислять значения функции,
идя от листьев к корню. Однако есть и другой способ.

     "Обратной польской записью" (или "постфиксной записью") вы-
ражения  называют  запись,  где знак функции стоит после всех ее
аргументов, а скобки не используются. Вот несколько примеров:

          f(2)                  2 f
          f(g(2))               2 g f
          s(2,t(7))             2 7 t s
          s(2, u(2, s(5,3))     2 2 5 3 s u s

Постфиксная  запись  выражения  позволяет удобно вычислять его с
помощью "стекового калькулятора". Этот калькулятор  имеет  стек,
который  мы  будем представлять себе расположенным горизонтально
(числа вынимаются и кладутся справа). При нажатии на  клавишу  с
числом  это число кладется в стек. При нажатии на функциональную
клавишу соответствующая функция применяется к  нескольким  аргу-
ментам у вершины стека. Например, если в стеке были числа
        2 3 4 5 6
и  нажата  функциональная клавиша s, соотвтетствующая функции от
двух аргументов, то в стеке окажутся числа
        2 3 4 s(5,6)

Перейдем теперь к нашей задаче. В процессе  вычисления  значения
функции  f мы будем работать со стеком чисел, а также с последо-
вательностью чисел и символов "f", "l", "r", "h", которую мы бу-
дем интерпретировать как последовательность  нажатий  кнопок  на
стековом калькуляторе.  Инвариант такой:

      если стек чисел представляет собой текущее состояние
      стекового калькулятора, то после нажатия всех клавиш
      последовательности в стеке останется единственное
      число, и оно будет искомым ответом.

Пусть нам требуется вычислить значение, к примеру, f(100). Тогда
вначале мы помещаем в стек число 100, а  последовательность  со-
держит  единственный  символ "f". (При этом инвариант соблюдает-
ся.) Далее с последовательностью и стеком выполняются такие пре-
образования:


 старый       старая           новый       новая
 стек      последовательность  стек    последовательность

  X          x P               X x           P
  X x        l P               X l(x)        P
  X x        r P               X r(x)        P
  X x y z    h P               X h(x,y,z)    P
  X 0        f P               X a           P
  X x        f P               X             x x l f x r f h P

Обозначения: x, y, z,.. - числа, X - последовательность чисел, P
- последовательность чисел и символов "f", "l", "r", "h". В пос-
ледней строке предполагается, что m не равно 0. Эта строка соот-
ветствует равенству

        f(x) = h(x, f(l(x)), f(r(x))),

Эти  преобразования выполняются, пока последовательность не ста-
нет пуста. В этот момент в стеке  окажется  единственное  число,
которое и будет ответом.

     Замечание.  Последовательность по существу представляет со-
бой стек отложенных заданий (вершина которого находится слева).
     Глава 9. Разные алгоритмы на графах

     9.1. Кратчайшие пути

     В этом разделе рассматриваются различные варианты одной за-
дач. Пусть имеется n городов, пронумерованных числами от 1 до n.
Для каждой пары городов с номерами i, j в таблице  a[i][j]  хра-
нится  целое число - цена прямого авиабилета из города i в город
j. Считается, что рейсы существуют между любыми городами, a[i,i]
= 0 при всех i, a[i][j] может отличаться от  a[j,i].  Наименьшей
стоимостью проезда из i в j считается минимально возможная сумма
цен  билетов  для маршрутов (в том числе с пересадками), ведущих
из i в j. (Она не превосходит a[i][j], но может быть меньше.)

     В предлагаемых ниже задачах требуется найти наименьшую сто-
имость проезда для некоторых пар городов при тех или иных  огра-
ничениях на массив a и на время работы алгоритма.

     9.1.1.  Предположим, что не существует замкнутых маршрутов,
для которых сумма цен отрицательна. Доказать, что в этом  случае
маршрут с наименьшей стоимостью существует.

     Решение. Маршрут длиной больше n всегда содержит цикл,  по-
этому минимум можно искать среди маршрутов длиной не более n,  а
их конечное число.

     Во всех следующих задачах предполагается,  что  это условие
(отсутствие циклов с отрицательной суммой) выполнено.

     9.1.2. Найти наименьшую стоимость проезда из 1-го города во
все остальные за время O(n в степени 3).

     Решение. Обозначим через МинСт(1,s,к) наименьшую  стоимость
проезда из 1 в s менее чем с k  пересадками.  Тогда  выполняется
такое соотношение:

   МинСт (1,s,k+1) = наименьшему из чисел МинСт(1,s,k) и
                     МинСт(1,i,k) + a[i][s] (i=1..n)

Как отмечалось выше, искомым ответом является  МинСт(1,i,n)  для
всех i=1..n.

     k:= 1;
     for i := 1 to n do begin x[i] := a[1][i]; end;
     {инвариант: x[i] := МинСт(1,i,k)}
     while k <> n do begin
     | for s := 1 to n do begin
     | | y[s] := x[s];
     | | for i := 1 to n do begin
     | | | if y[s] > x[i]+a[i][s] then begin
     | | | | y[s] := x[i]+a[i][s];
     | | | end;
     | | end
     | | {y[s] = МинСт(1,s,k+1)}
     | | for i := 1 to n do begin x[s] := y[s]; end;
     | end;
     | k := k + 1;
     end;

Приведенный  алгоритм называют алгоритмом динамического програм-
мирования, или алгоритмом Форда - Беллмана.

     9.1.3. Доказать, что программа останется  правильной,  если
не заводить массива y, а производить изменения в самом массиве x
(заменив в программе все вхождения буквы y на x и затем  удалить
ставшие лишними строки).

     Решение. Инвариант будет таков:
     МинСт(1,i,n) <= x[i] <= MинСт(1,i,k)

     Этот алгоритм может быть улучшен в двух  отношениях:  можно
за то же время O(n в степени 3) найти наименьшую стоимость  про-
езда i->j для ВСЕХ пар i,j (а не только с i=1), а  можно  сокра-
тить время работы до O(n в степени 2). Правда, в последнем  слу-
чае нам потребуется, чтобы все цены a[i][j] были неотрицательны.

     9.1.4. Найти наименьшую стоимость проезда i->j для всех i,j
за время O(n в степени 3).

     Решение. Для k = 0..n через А(i,j,k)  обозначим  наименьшую
стоимость маршрута из i в j, если в качестве пересадочных разре-
шено использовать только пункты с номерами не больше k. Тогда

     A(i,j,0) = a[i][j],
а
     A(i,j,k+1) = min (A(i,j,k), A(i,k+1,k)+A(k+1,j,k))

(два  варианта  соответствуют  неиспользованию  и  использованию
пункта k+1 в качестве пересадочного; отметим, что в нем  незачем
бывать более одного раза).
     Этот алгоритм называют алгоритмом Флойда.

     9.1.5.  Известны,  что  все  цены неотрицательны. Найти на-
именьшую стоимость проезда 1->i для всех i=1..n за время  O(n  в
степени 2).

     Решение. В процессе работы алгоритма некоторые города будут
выделенными (в начале - только город 1,  в  конце  -  все).  При
этом:

     для каждого выделенного города i хранится  наименьшая  сто-
имость пути 1->i; при этом известно, что минимум достигается  на
пути, проходящем только через выделенные города;
     для каждого невыделенного города i хранится наименьшая сто-
имость пути 1->i, в котором в качестве промежуточных используют-
ся только выделенные города.

     Множество  выделенных городов расширяется на основании сле-
дующего замечания: если среди всех  невыделенных  городов  взять
тот,  для которого хранимое число минимально, то это число явля-
ется истинной наименьшей стоимостью. В самом  деле,  пусть  есть
более  короткий  путь.  Рассмотрим  первый невыделенный город на
этом пути - уже до него путь длиннее! (Здесь существенна неотри-
цательность цен.)
     Добавив выбранный город к выделенным, мы должны  скорректи-
ровать информацию, хранимую для невыделенных городов.  При  этом
достаточно учесть лишь пути, в которых новый город является пос-
ледним пунктом пересадки, а это легко сделать, так как минималь-
ную стоимость проезда в новый город мы уже знаем.
     При самом бесхитростном способе хранения множества выделен-
ных городов (в булевском векторе)  добавление  одного  города  к
числу выделенных требует времени O(n).
     Этот алгоритм называют алгоритмом Дейкстры.

     Отыскании кратчайшего пути имеет естественную интерпретацию
в терминах матриц. Пусть A - матрица цен одной аваиакомпании,  а
B  -  матрица цен другой. (Мы считаем, что диагональные элементы
матриц равны 0.) Пусть мы хотим лететь с одной пересадкой,  при-
чем  сначала самолетом компании A, а затем - компании B. Сколько
нам придется заплатить, чтобы попасть из города i в город j?

     9.1.6. Доказать, что эта  матрица  вычисляется  по  обычной
формуле  для произведения матриц, только вместо суммы надо брать
минимум, а вместо умножения - сумму.

     9.1.7. Доказать, что таким образом определенное  произведе-
ние матриц ассоциативно.

     9.1.8. Доказать, что задача о кратчайших путях эквивалентна
вычислению "бесконечной степени" матрицы  цен  A:  в  последова-
тельности  A, A*A, A*A*A,... все элементы, начиная с некоторого,
равны искомой матрице стоимостей кратчайших путей. (Если нет от-
рицательных циклов!)

     9.1.9.  Начиная  с  какого элемента можно гарантировать ра-
венство в предыдущей задаче?

     Обычное  (не  модифицированное) умножение матриц тоже может
оказаться полезным, только матрицы  должны  быть  другие.  Пусть
есть не все рейсы (как в следующем разделе), а только некоторые,
a[i,j]  равно  1,  если рейс есть, и 0, если рейса нет. Возведем
матрицу a (обычным образом) в степень k и посмотрим на ее i-j-ый
элемент.

     9.1.10. Чему он равен?

     Ответ. Числу различных способов попасть  из  i  в  j  за  k
рейсов.

     Случай,  когда есть не все рейсы, можно свести к исходному,
введя фиктивные  рейсы  с  бесконечно  большой  (или  достаточно
большой)  стоимостью. Тем не менее возникает такой вопрос. Число
реальных рейсов может быть существенно меньше n*n, поэтому инте-
ресны алгоритмы, которые работают эффективно в  такой  ситуации.
Исходные  данные  естественно  представлять тогда в такой форме:
для каждого города известно число выходящих из него  рейсов,  их
пункты назначения и цены.

     9.1.11.  Доказать,  что алгоритм Дейкстры можно модифициро-
вать так, чтобы для n городов и k маршрутов он требовал не более
C*(n+k log n) операций.
     Указание. Что надо сделать на каждом шаге? Выбрать  невыде-
ленный город с минимальной стоимостью и скорректировать цены для
всех  городов,  в  которые из него есть маршруты. Если бы кто-то
сообщал нам, для какого города стоимость минимальна, то  хватило
бы C*(n+k) действий. А поддержание сведений о том, какой элемент
в  массиве  минимален  (см. задачу 6.4.1 в главе о типах данных)
обходится еще в множитель log n.

     9.2. Связные компоненты, поиск в глубину и ширину

     Наиболее простой случай задачи о кратчайших  путях  -  если
все цены равны 0 или бесконечны. Другими словами, мы интересуем-
ся  возможностью попасть из i в j, но за ценой не постоим (и она
нас не интересует). В других терминах: мы имеем  ориентированный
граф (картинку из точек, некоторые из которых соединены стрелка-
ми) и нас интересуют вершины, доступные из данной.

     Для  этого  случая  задачи о кратчайших путях приведенные в
предыдущем разделе алгоритмы - не наилучшие. В самом деле, более
быстрая  рекурсивная  программа  решения этой задачи приведена в
главе 7 (Рекурсия), а нерекурсивная - в главе 6  (Типы  данных).
Сейчас  нас  интересует  такая задача: не просто перечислить все
вершины, доступные из данной, но перечислить их  в  определенном
Предыдущая страница Следующая страница
1 ... 64 65 66 67 68 69 70  71 72 73 74 75 76 77 ... 85
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама