F2Cmax
| Задача: | 
| Рассмотрим задачу: 
 | 
Описание алгоритма
Пусть  — время выполнения -ой работы на первом станке, а  — на втором.
- Алгоритм строит два списка и . Изначально они пусты. Также поддерживается множество еще не распределенных по спискам и работ
-  Пока множество  не пусто, распределяем работы по спискам следующим образом:
- находим такие индексы и , что ,
- если минимум достигается на первом станке (иными словами ), то поставим работу в конец списка , иначе ставим в начало списка ,
- удаляем работу из множества .
 
- Рассмотрим список — конкатенацию и . Утверждается, что этот список является оптимальной перестановкой работ как на первом, так и на втором станке. Далее расставляем подряд работы на первом станке согласно перестановке, после чего ставим в том же порядке работы на втором станке, при этом избегая одновременного выполнения одной и той же работы.
Доказательство корректности алгоритма
| Теорема: | 
| Существует оптимальное расписание, в котором станки выполняют работы в одном и том же порядке. | 
| Доказательство: | 
| Предположим обратное: что не существует оптимального расписания с одинаковыми перестановками работ на станках.Рассмотрим некоторое оптимальное расписание с максимальным по длине общим префиксом на станках. Пусть его длина равна , где . Пусть на позиции на первом и втором станках стоит работа , а на втором станке на позиции стоит работа . Тогда заметим, что если мы поставим работу на первом станке сразу после работы , то последовательные работы с по (см. рис. 1) по-прежнему будут успевать выполниться, так как на втором станке они выполняются в текущем расписании после . Таким образом нам удалось увеличить длину наибольшего общего префикса, а так как по нашему предположению она была максимальна, то предположение неверно и искомое расписание с одинаковым порядком выполнения работ на обоих станках существует. | 
Таким образом задача сводится к поиску этой перестановки. Докажем, что полученный приведенным выше алгоритмом список является оптимальной перестановкой работ.
| Лемма (1): | 
| Если для каких-то работ  и  из списка  верно неравенство , то работа  встречается в списке  раньше, чем . | 
| Доказательство: | 
| Пусть . Случай рассматривается аналогично.Так как , то работа . Работа либо стоит в , либо она стоит в и при этом . Заметим, что в обоих случаях она расположена позже (в силу нашего построения), чем работа . | 
| Лемма (2): | 
| Пусть имеем произвольное расписание, в котором работа  идет сразу же после работы . Тогда если , то можем поменять местами эти работы без ухудшения целевой функции. | 
| Доказательство: | 
| Пусть — время, прошедшее с начала выполнения работы на первом станке до окончания работы на втором станке. Рассмотрим возможные случаи расположения работ и (см. Рис. 2) 
 Таким образом, . Иначе говоря, . Аналогично,Так как , то из условия леммы имеем . Добавив к обеим частям, получим, что , то есть и при смене местами работ и ответ не ухудшается. | 
| Теорема: | 
| Построенная перестановка  является оптимальной. | 
| Доказательство: | 
| Рассмотрим произвольную перестановку . Пусть перестановки и имеют общий префикс длины . Пусть и . Рассмотрим множество работ . Заметим, что для любой работы верно, что , так как если было бы верно обратное, то есть , то по лемме 1 было бы верно, что идет раньше , что неверно. Очевидно, что в перестановке работа будет стоять после (иначе общий префикс был бы длиннее), то заметим, что в этой перестановке для работы и для предыдущей работы верно (так как ), то по лемме 2 можем поменять местами работы и без ухудшения ответа. То такими операциями сможем дойти до пары работ и , которые при смене увеличат общий префикс перестановок и .Таким образом любая перестановка сводится к нашей без ухудшения ответа такими операциями, что подтверждает оптимальность перестановки | 
Псевдокод
  function F2Cmax(p: int[n][2]): list<int>
     list<int> L = 
     list<int> R = 
     set<int> X = 
     while X 
        Найти i и j, такие что 
        if j == 1
           L.addLast(i)
        else 
           R.addFirst(i)
        X.remove(i)
     list<int> T = L ++ R
     return T
Сложность алгоритма
Заметим, что на каждом шаге алгоритма мы выбираем минимум из оставшихся элементов за (либо предварительной сортировкой, либо с помощью любой структуры данных, поддерживающей нахождение минимума и удаление за , например, кучи). А так как мы делаем это раз, алгоритм работает за .
См. также
Источники информации
- Peter Brucker. «Scheduling Algorithms» — «Springer», 2006 г. — 175 стр. — ISBN 978-3-540-69515-8


