Главная · Поиск книг · Поступления книг · 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 ... 38 39 40 41 42 43 44  45 46 47 48 49 50 51 ... 85
ся.) Далее с последовательностью и стеком выполняются такие пре-
образования:


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

  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 или бесконечны.)

     9.2.1.  Придумать  алгоритм  решения  этой  задачи с числом
действий не более C*(число ребер, выходящих из интересующих  нас
вершин).

     Решение.  Эта  задача  рассматривалась в главе 6 (Типы дан-
ных), 6.3.7 - 6.3.8. Здесь мы приведём подробное решение.  Пусть
num[i]  -  количество  ребер,  выходящих  из  i,  out[i][1],...,
out[i][num[i]] - вершины, куда ведут ребра. Вот программа,  при-
ведённая ранее:

  procedure Доступные (i: integer);
  |   {напечатать все вершины, доступные из i, включая i}
  | var  X: подмножество 1..n;
  |      P: подмножество 1..n;
  |      q, v, w: 1..n;
  |      k: integer;
  begin
  | ...сделать X, P пустыми;
  | writeln (i);
  | ...добавить i к X, P;
  | {(1) P = множество напечатанных вершин; P содержит i;
  |  (2) напечатаны только доступные из i вершины;
  |  (3) X - подмножество P;
  |  (4) все напечатанные вершины, из которых выходит
  |      ребро в ненапечатанную вершину, принадлежат X}
  | while X непусто do begin
  | | ...взять какой-нибудь элемент X в v;
  | | for k := 1 to num [v] do begin
  | | | w := out [v][k];
  | | | if w не принадлежит P then begin
  | | | | writeln (w);
  | | | | добавить w в P;
  | | | | добавить w в X
  | | | end;
  | | end;
  | end;
  end;

Тогда нам было безразлично, какой именно элемент множества X вы-
бирается. Если мы будем считать X очередью (первым пришел - пер-
мым ушел), то эта программа напечатает все вершины, доступные из
i, в порядке возрастания их расстояния  от  i  (числа  ребер  на
кратчайшем пути из i). Докажем это.

     Обозначим  через V(k) множество всех вершин, расстояние ко-
торых от i (в описанном смысле) равно k. Имеет место такое соот-
ношение:

 V(k+1) = (концы ребер с началами в V(k))-V(0)-V(1)-...-V(k)

(знак "-" обозначает вычитание множеств). Докажем, что для любо-
го k=0,1,2... в ходе работы программы будет такой момент  (после
очередной итерации цикла while), когда

     в очереди стоят все элементы V(k) и только они
     напечатаны все элементы V(1),...,V(k)
Предыдущая страница Следующая страница
1 ... 38 39 40 41 42 43 44  45 46 47 48 49 50 51 ... 85
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама