F2Cmax — различия между версиями
AMaltsev (обсуждение | вклад) |
м (rollbackEdits.php mass rollback) |
||
(не показано 5 промежуточных версий 2 участников) | |||
Строка 14: | Строка 14: | ||
<li> Пока множество <tex> X </tex> не пусто, распределяем работы по спискам следующим образом: | <li> Пока множество <tex> X </tex> не пусто, распределяем работы по спискам следующим образом: | ||
<ul> | <ul> | ||
− | <li> находим такие индексы <tex> i </tex> и <tex> j </tex>, что <tex>p_{ij} = \min \{ p_{ij} \mid i \in X | + | <li> находим такие индексы <tex> i </tex> и <tex> j </tex>, что <tex>p_{ij} = \min \{ p_{ij} \mid i \in X \land j = 1, 2\}</tex>, </li> |
<li>если минимум достигается на первом станке (иными словами <tex> j = 1 </tex>), то поставим работу <tex> i </tex> в конец списка <tex> L </tex>, иначе ставим в начало списка <tex> R </tex>, </li> | <li>если минимум достигается на первом станке (иными словами <tex> j = 1 </tex>), то поставим работу <tex> i </tex> в конец списка <tex> L </tex>, иначе ставим в начало списка <tex> R </tex>, </li> | ||
<li>удаляем работу <tex> i </tex> из множества <tex> X </tex>. </li> | <li>удаляем работу <tex> i </tex> из множества <tex> X </tex>. </li> | ||
</ul> | </ul> | ||
</li> | </li> | ||
− | <li> Рассмотрим список <tex> T = L + R</tex> - конкатенацию <tex> L</tex> и <tex>R</tex>. Утверждается, что этот список является оптимальной перестановкой работ как на первом, так и на втором станке. Далее расставляем подряд работы на первом станке согласно перестановке, после чего ставим в том же порядке работы на втором станке, при этом избегая одновременного выполнения одной и той же работы. </li> | + | <li> Рассмотрим список <tex> T = L ~\texttt{++}~ R</tex> {{---}} конкатенацию <tex> L</tex> и <tex>R</tex>. Утверждается, что этот список является оптимальной перестановкой работ как на первом, так и на втором станке. Далее расставляем подряд работы на первом станке согласно перестановке, после чего ставим в том же порядке работы на втором станке, при этом избегая одновременного выполнения одной и той же работы. </li> |
</ol> | </ol> | ||
Строка 31: | Строка 31: | ||
[[Файл:f2cmax_first_fixed.png|400px|thumb|right|Рис. 1]] | [[Файл:f2cmax_first_fixed.png|400px|thumb|right|Рис. 1]] | ||
Предположим обратное: что не существует оптимального расписания с одинаковыми перестановками работ на станках. | Предположим обратное: что не существует оптимального расписания с одинаковыми перестановками работ на станках. | ||
− | Рассмотрим некоторое оптимальное расписание с максимальным по длине общим префиксом на станках. Пусть его длина равна <tex> k </tex>, где <tex> k < n </tex>. Пусть на <tex> k </tex> позиции на первом и втором станках стоит работа <tex> i </tex>, а на втором станке на позиции <tex> k + 1 </tex> стоит работа <tex> j </tex>. Тогда заметим, что если мы поставим работу <tex> j </tex> на первом станке сразу после работы <tex> i </tex>, то последовательные работы с <tex> h </tex> по <tex> m </tex> (см. | + | Рассмотрим некоторое оптимальное расписание с максимальным по длине общим префиксом на станках. Пусть его длина равна <tex> k </tex>, где <tex> k < n </tex>. Пусть на <tex> k </tex> позиции на первом и втором станках стоит работа <tex> i </tex>, а на втором станке на позиции <tex> k + 1 </tex> стоит работа <tex> j </tex>. Тогда заметим, что если мы поставим работу <tex> j </tex> на первом станке сразу после работы <tex> i </tex>, то последовательные работы с <tex> h </tex> по <tex> m </tex> (см. рис. 1) по-прежнему будут успевать выполниться, так как на втором станке они выполняются в текущем расписании после <tex> j </tex>. Таким образом нам удалось увеличить длину наибольшего общего префикса, а так как по нашему предположению она была максимальна, то предположение неверно и искомое расписание с одинаковым порядком выполнения работ на обоих станках существует. |
}} | }} | ||
− | Таким образом задача сводится к поиску этой | + | Таким образом задача сводится к поиску этой перестановки. Докажем, что полученный приведенным выше алгоритмом список является оптимальной перестановкой работ. |
{{лемма | {{лемма | ||
|id=lemma1 | |id=lemma1 | ||
|about=1 | |about=1 | ||
− | |statement= Если для каких-то работ <tex> i </tex> и <tex> j </tex> из списка <tex> T </tex> верно неравенство <tex> \min(p_{i1}, p_{j2}) < | + | |statement= Если для каких-то работ <tex> i </tex> и <tex> j </tex> из списка <tex> T </tex> верно неравенство <tex> \min(p_{i1}, p_{j2}) < \min(p_{j1}, p_{i2}) </tex>, то работа <tex> i </tex> встречается в списке <tex> T </tex> раньше, чем <tex> j </tex>. |
|proof= | |proof= | ||
Пусть <tex> p_{i1} < p_{j2} </tex>. Случай <tex> p_{i1} > p_{j2} </tex> рассматривается аналогично. | Пусть <tex> p_{i1} < p_{j2} </tex>. Случай <tex> p_{i1} > p_{j2} </tex> рассматривается аналогично. | ||
Строка 52: | Строка 52: | ||
|statement= Пусть имеем произвольное расписание, в котором работа <tex> j </tex> идет сразу же после работы <tex> i </tex>. Тогда если <tex> \min(p_{j1}, p_{i2}) \leqslant \min(p_{i1}, p_{j2}) </tex>, то можем поменять местами эти работы без ухудшения целевой функции. | |statement= Пусть имеем произвольное расписание, в котором работа <tex> j </tex> идет сразу же после работы <tex> i </tex>. Тогда если <tex> \min(p_{j1}, p_{i2}) \leqslant \min(p_{i1}, p_{j2}) </tex>, то можем поменять местами эти работы без ухудшения целевой функции. | ||
|proof= | |proof= | ||
− | [[Файл:f2cmax_fixed.png|200px|thumb|right|Рис. 2 - Расположение последовательных работ]] | + | [[Файл:f2cmax_fixed.png|200px|thumb|right|Рис. 2 {{---}} Расположение последовательных работ]] |
Пусть <tex> w_{ij} </tex> {{---}} время, прошедшее с начала выполнения работы <tex> i </tex> на первом станке до окончания работы <tex> j </tex> на втором станке. | Пусть <tex> w_{ij} </tex> {{---}} время, прошедшее с начала выполнения работы <tex> i </tex> на первом станке до окончания работы <tex> j </tex> на втором станке. | ||
Строка 81: | Строка 81: | ||
Аналогично, <tex> w_{ji} = \max (p_{j1} + \max(p_{i1}, p_{j2}) + p_{i2}, \Delta + p_{i2} + p_{j2}) </tex> | Аналогично, <tex> w_{ji} = \max (p_{j1} + \max(p_{i1}, p_{j2}) + p_{i2}, \Delta + p_{i2} + p_{j2}) </tex> | ||
− | Так как <tex> \min(a, b) = - \max(-a, -b)</tex>, то из условия леммы имеем <tex> \max(-p_{i1}, -p_{j2}) \leqslant \max(-p_{j1}, -p_{i2}) </tex>. | + | Так как <tex> \min(a, b) = - \max(-a, -b)</tex>, то из условия леммы имеем <tex> \max(-p_{i1}, -p_{j2}) \leqslant \max(-p_{j1}, -p_{i2}) </tex>. Добавив <tex> p_{i1} + p_{i2} + p_{j1} + p_{j2} </tex> к обеим частям, получим, что <tex> p_{j1} + \max(p_{i1}, p_{j2}) + p_{i2} \leqslant p_{i1} + \max(p_{j1}, p_{i2}) + p_{j2} </tex>, то есть <tex> w_{ji} \leqslant w_{ij} </tex> и при смене местами работ <tex> i </tex> и <tex> j </tex> ответ не ухудшается. |
}} | }} | ||
Строка 101: | Строка 101: | ||
==Псевдокод== | ==Псевдокод== | ||
− | '''function''' F2Cmax( | + | '''function''' F2Cmax(p: '''int'''[n][2]): '''list<int>''' |
− | '''list''' L = <tex>\varnothing </tex> | + | '''list<int>''' L = <tex>\varnothing </tex> |
− | '''list''' R = <tex>\varnothing </tex> | + | '''list<int>''' R = <tex>\varnothing </tex> |
− | '''set''' X = <tex>\{1, \ | + | '''set<int>''' X = <tex>\{1, \ldots, n\}</tex> |
− | '''while''' | + | '''while''' X <tex>\neq \varnothing</tex> |
− | Найти i | + | Найти i и j, такие что <tex>p_{ij} = \min \{ p_{ij} \mid i \in X \land j = 1, 2\}</tex> |
'''if''' j == 1 | '''if''' j == 1 | ||
L.addLast(i) | L.addLast(i) | ||
Строка 112: | Строка 112: | ||
R.addFirst(i) | R.addFirst(i) | ||
X.remove(i) | X.remove(i) | ||
− | '''list''' T = L + R | + | '''list<int>''' T = L ++ R |
'''return''' T | '''return''' T | ||
==Сложность алгоритма== | ==Сложность алгоритма== | ||
− | Заметим, что на каждом шаге алгоритма мы выбираем минимум из оставшихся элементов за <tex>O(\log n)</tex> (либо предварительной [[Сортировка|сортировкой]], либо с помощью любой структуры данных, поддерживающей нахождение минимума и удаление за <tex>O(\log n)</tex>, например [[Двоичная_куча|кучи]]). А так как мы делаем это <tex> n </tex> раз, алгоритм работает за <tex>O(n\log n)</tex>. | + | Заметим, что на каждом шаге алгоритма мы выбираем минимум из оставшихся элементов за <tex>O(\log n)</tex> (либо предварительной [[Сортировка|сортировкой]], либо с помощью любой структуры данных, поддерживающей нахождение минимума и удаление за <tex>O(\log n)</tex>, например, [[Двоичная_куча|кучи]]). А так как мы делаем это <tex> n </tex> раз, алгоритм работает за <tex>O(n\log n)</tex>. |
==См. также== | ==См. также== |
Текущая версия на 19:27, 4 сентября 2022
Задача: |
Рассмотрим задачу:
|
Содержание
Описание алгоритма
Пусть
- Алгоритм строит два списка и . Изначально они пусты. Также поддерживается множество еще не распределенных по спискам и работ
- Пока множество
- находим такие индексы и , что ,
- если минимум достигается на первом станке (иными словами ), то поставим работу в конец списка , иначе ставим в начало списка ,
- удаляем работу из множества .
не пусто, распределяем работы по спискам следующим образом:
- Рассмотрим список — конкатенацию и . Утверждается, что этот список является оптимальной перестановкой работ как на первом, так и на втором станке. Далее расставляем подряд работы на первом станке согласно перестановке, после чего ставим в том же порядке работы на втором станке, при этом избегая одновременного выполнения одной и той же работы.
Доказательство корректности алгоритма
Теорема: |
Существует оптимальное расписание, в котором станки выполняют работы в одном и том же порядке. |
Доказательство: |
Предположим обратное: что не существует оптимального расписания с одинаковыми перестановками работ на станках. Рассмотрим некоторое оптимальное расписание с максимальным по длине общим префиксом на станках. Пусть его длина равна , где . Пусть на позиции на первом и втором станках стоит работа , а на втором станке на позиции стоит работа . Тогда заметим, что если мы поставим работу на первом станке сразу после работы , то последовательные работы с по (см. рис. 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