<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zemskovk</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zemskovk"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Zemskovk"/>
		<updated>2026-06-11T16:46:37Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54105</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54105"/>
				<updated>2016-05-19T02:54:26Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁#.D0.9E.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D1.81.D0.B2.D1.8F.D0.B7.D1.8C_.CE.A3.E2.82.81_.D0.B8_NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано в книге [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] на страницах 174 {{---}} 178.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;p_1&amp;lt;/tex&amp;gt; время выполнения работы на первом станке, за &amp;lt;tex&amp;gt;p_2&amp;lt;/tex&amp;gt; время выполнения работы на втором станке.&lt;br /&gt;
  &lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
Для представления работы в памяти будем использовать следующую структуру:&lt;br /&gt;
 '''struct''' Job:&lt;br /&gt;
     '''int''' p1    &amp;lt;font color = green&amp;gt;// Время выполнения на первом станке&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''int''' p2    &amp;lt;font color = green&amp;gt;// Время выполнения на втором станке&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Приведём реализацию самого алгоритма:&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;// Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(J: '''List&amp;lt;Job&amp;gt;'''): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
     &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I = работа с минимальным значением &amp;lt;tex&amp;gt;\min(p1, \ \ p2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p1 \leqslant p2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54104</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54104"/>
				<updated>2016-05-19T02:34:22Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁#.D0.9E.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D1.81.D0.B2.D1.8F.D0.B7.D1.8C_.CE.A3.E2.82.81_.D0.B8_NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;p_1&amp;lt;/tex&amp;gt; время выполнения работы на первом станке, за &amp;lt;tex&amp;gt;p_2&amp;lt;/tex&amp;gt; время выполнения работы на втором станке.&lt;br /&gt;
  &lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
Для представления работы в памяти будем использовать следующую структуру:&lt;br /&gt;
 '''struct''' Job:&lt;br /&gt;
     '''int''' p1    &amp;lt;font color = green&amp;gt;// Время выполнения на первом станке&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''int''' p2    &amp;lt;font color = green&amp;gt;// Время выполнения на втором станке&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Приведём реализацию самого алгоритма:&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;// Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(J: '''List&amp;lt;Job&amp;gt;'''): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
     &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I = работа с минимальным значением &amp;lt;tex&amp;gt;\min(p1, \ \ p2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p1 \leqslant p2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54103</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54103"/>
				<updated>2016-05-19T02:23:08Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁#.D0.9E.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D1.81.D0.B2.D1.8F.D0.B7.D1.8C_.CE.A3.E2.82.81_.D0.B8_NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Обозначим за &amp;lt;tex&amp;gt;p_1&amp;lt;/tex&amp;gt; время выполнения работы на первом станке, за &amp;lt;tex&amp;gt;p_2&amp;lt;/tex&amp;gt; время выполнения работы на втором станке.&lt;br /&gt;
  &lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;// Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(J: '''List&amp;lt;int[2]&amp;gt;'''): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
     &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I = работа с минимальным значением &amp;lt;tex&amp;gt;\min(p[1], \ \ p[2])&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p[1] \leqslant p[2]&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54102</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54102"/>
				<updated>2016-05-19T02:19:35Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁#.D0.9E.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D1.81.D0.B2.D1.8F.D0.B7.D1.8C_.CE.A3.E2.82.81_.D0.B8_NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;// Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(J: '''List&amp;lt;int[2]&amp;gt;'''): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
     &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I = работа с минимальным значением &amp;lt;tex&amp;gt;\min(p[1], \ \ p[2])&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p[1] \leqslant p[2]&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54101</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54101"/>
				<updated>2016-05-19T02:18:55Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁#.D0.9E.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D1.81.D0.B2.D1.8F.D0.B7.D1.8C_.CE.A3.E2.82.81_.D0.B8_NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;//Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(J: '''List&amp;lt;int[2]&amp;gt;'''): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
     &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I = работа с минимальным значением &amp;lt;tex&amp;gt;\min(p[1], \ \ p[2])&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p[1] \leqslant p[2]&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54100</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54100"/>
				<updated>2016-05-19T02:18:30Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁#.D0.9E.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D1.81.D0.B2.D1.8F.D0.B7.D1.8C_.CE.A3.E2.82.81_.D0.B8_NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;//Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(J: '''List&amp;lt;int[2]&amp;gt;'''): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
     &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I =  работа с минимальным значением &amp;lt;tex&amp;gt;\min(p[1], \ \ p[2])&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p[1] \leqslant p[2]&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54099</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54099"/>
				<updated>2016-05-19T02:10:46Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁#.D0.9E.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D1.81.D0.B2.D1.8F.D0.B7.D1.8C_.CE.A3.E2.82.81_.D0.B8_NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
    &amp;lt;font color = green&amp;gt;//Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''function''' scheduling('''List&amp;lt;int&amp;gt;''': J): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
        &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
        &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
             I =  работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
                 &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''else''' &lt;br /&gt;
                 &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54098</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54098"/>
				<updated>2016-05-19T02:08:34Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Корректность и оптимальность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.2.png|500px|thumb|Рис. 1. Исходная сеть]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.9.b.png|500px|thumb|Рис. 2. Расширение сети]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
===Корректность и оптимальность алгоритма===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
:&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
:&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:В противном случае&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b)&amp;lt;/tex&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно&amp;lt;ref&amp;gt;Описано в Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 133 стр.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54096</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54096"/>
				<updated>2016-05-18T19:06:32Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.2.png|500px|thumb|Рис. 1. Исходная сеть]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.9.b.png|500px|thumb|Рис. 2. Расширение сети]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
===Корректность и оптимальность алгоритма===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
:&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
:&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно&amp;lt;ref&amp;gt;Описано в Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 133 стр.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54095</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54095"/>
				<updated>2016-05-18T19:04:45Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.2.png|500px|thumb|Рис. 1. Исходная сеть]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.9.b.png|500px|thumb|Рис. 2. Расширение сети]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
===Корректность и оптимальность алгоритма===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
:&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
:&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно&amp;lt;ref&amp;gt;Описано в Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 133 стр.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54094</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54094"/>
				<updated>2016-05-18T18:59:43Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁ | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{J}&amp;lt;/tex&amp;gt; {{---}} список работ, которые надо выполнить,&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{List1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \mathtt{List2} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
    &amp;lt;font color = green&amp;gt;//Функция принимает список работ J и возвращает список с расписанием работ.&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''function''' scheduling('''List&amp;lt;int&amp;gt;''': J): '''List&amp;lt;int&amp;gt;''' &lt;br /&gt;
        &amp;lt;tex&amp;gt; \mathtt{List1} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
        &amp;lt;tex&amp;gt;\mathtt{List2} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''while''' &amp;lt;tex&amp;gt;J \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
             I =  работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
                 &amp;lt;tex&amp;gt; \mathtt{List1} = \mathtt{List1} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
             '''else''' &lt;br /&gt;
                 &amp;lt;tex&amp;gt;\mathtt{List2} = I \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''return''' &amp;lt;tex&amp;gt;\mathtt{List1} \cup  \mathtt{List2} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54093</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54093"/>
				<updated>2016-05-18T18:46:06Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этой теоремы может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[Классы_NP,_coNP,_Σ₁,_Π₁ | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Доказательство описано тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Будем использовать следующий алгоритм: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
J {{---}} список работ, которые надо выполнить, &amp;lt;tex&amp;gt; \mathrm{FirstList}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{SecondList} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{FirstList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{SecondList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{FirstList} = \mathrm{FirstList} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{SecondList} = I \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = \mathrm{FirstList} \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=54092</id>
		<title>J2ni2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=54092"/>
				<updated>2016-05-18T18:38:38Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;J2 \mid n_i \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*Дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка.&lt;br /&gt;
*Для каждой работы известно её время выполнения на каждом станке &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Для каждой работы известна последовательность &amp;lt;tex&amp;gt;O_{i1}, \ O_{i2} \ \ldots \ O_{ik}&amp;lt;/tex&amp;gt; станков {{---}} порядок, в котором нужно выполнить работу. &lt;br /&gt;
*В каждой последовательности &amp;lt;tex&amp;gt;O_{i}&amp;lt;/tex&amp;gt; не более двух элементов.&lt;br /&gt;
Требуется минимизировать время окончания выполнения всех работ. }}&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; {{---}} первый станок. &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; {{---}} второй станок. &lt;br /&gt;
&lt;br /&gt;
Разобьем все работы на четыре множества:&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Решим задачу [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; и для &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; независимо. Получим расписание &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда оптимальное расписание для нашей задачи будет следующим:&lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Примечание''': во время выполнения &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; могут возникнуть простои &lt;br /&gt;
из-за того, что работа ещё не выполнилась на предыдущем станке.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;T_{j}(x)&amp;lt;/tex&amp;gt; {{---}} время выполнения множества работ &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; на станке &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G_{j}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые нужно сделать хотя бы раз на &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;-м станке, то есть &amp;lt;tex&amp;gt;G_{1} = I_{1} \cup I_{12} \cup I_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1 &lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, обладает следующим свойством: один из станков работает без простоев.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим два случая:&lt;br /&gt;
#&amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) \geqslant T_{2}(I_{21}) &amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Тогда &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{1} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#&amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) &amp;lt; T_{2}(I_{21}) &amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Тогда &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{2} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
[[Файл: j2ni2cmax.jpg|400px|thumb|right|&lt;br /&gt;
Рис. 1 {{---}} Расположение  работ.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
В серой области могут быть прерывания.&lt;br /&gt;
]]&lt;br /&gt;
Корректность алгоритма очевидна.&lt;br /&gt;
Докажем оптимальность.&lt;br /&gt;
&lt;br /&gt;
Пусть, для опеределенности &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим станок на котором достигается &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
*Если это &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;, то оптимальность очевидна &amp;lt;tex&amp;gt;(C_{max} \geqslant \sum\limits_{i \in G_{1}} p_{i1})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Иначе &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; достигается на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда либо &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний и оптимальность очевидна.&lt;br /&gt;
Или есть прерывания.&lt;br /&gt;
Тогда целевая функция равна ответу задачи [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для работ &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt;, который оптимален.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Время работы алгоритма равно времени работы алгоритма  [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]], то есть &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 179 {{---}} 180 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54091</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54091"/>
				<updated>2016-05-18T17:43:09Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая:&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;. Будем строить расписание с двух концов:&lt;br /&gt;
##*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt; в том же порядке, что и на первом станке.&lt;br /&gt;
##*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} \leqslant b_{y}&amp;lt;/tex&amp;gt;. Сводится к первому, если поменять местами станки и соответствующие списки времён выполнения, при этом надо заново выполнить пункты 1,2 и 3. При выдаче ответа меняем станки обратно местами.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется три блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.&amp;lt;br&amp;gt;//Функция возвращает пару из расписания для первого станка и расписания для второго станка.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans = пара из расписания для первого станка и расписания для второго станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158{{---}}160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54059</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54059"/>
				<updated>2016-05-17T17:06:42Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.2.png|500px|thumb|Рис. 1 - Исходная сеть]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.9.b.png|500px|thumb|Рис. 2 - Расширение сети]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
===Корректность и оптимальность алгоритма===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
* &amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно&amp;lt;ref&amp;gt;Описано в Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 133 стр.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=54058</id>
		<title>J2ni2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=54058"/>
				<updated>2016-05-17T17:05:28Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;J2 \mid n_i \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*Дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка.&lt;br /&gt;
*Для каждой работы известно её время выполнения на каждом станке &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Для каждой работы известна последовательность &amp;lt;tex&amp;gt;O_{i1}, \ O_{i2} \ \ldots \ O_{ik}&amp;lt;/tex&amp;gt; станков {{---}} порядок, в котором нужно выполнить работу. &lt;br /&gt;
*В каждой последовательности &amp;lt;tex&amp;gt;O_{i}&amp;lt;/tex&amp;gt; не более двух элементов.&lt;br /&gt;
Требуется минимизировать время окончания выполнения всех работ. }}&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; - первый станок. &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; - второй станок. &lt;br /&gt;
&lt;br /&gt;
Разобьем все работы на четыре множества:&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Решим задачу [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; и для &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; независимо. Получим расписание &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда оптимальное расписание для нашей задачи будет следующим:&lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Примечание: во время выполнения &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; могут возникнуть простои &lt;br /&gt;
из-за того, что работа ещё не выполнилась на предыдущем станке.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;T_{j}(x)&amp;lt;/tex&amp;gt; {{---}} время выполнения множества работ &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; на станке &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G_{j}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые нужно сделать хотя бы раз на &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;-м станке, то есть &amp;lt;tex&amp;gt;G_{1} = I_{1} \cup I_{12} \cup I_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1 &lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, обладает следующим свойством: один из станков работает без простоев.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим два случая:&lt;br /&gt;
#&amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) \geqslant T_{2}(I_{21}) &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{1} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#&amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) &amp;lt; T_{2}(I_{21}) &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{2} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
[[Файл: j2ni2cmax.jpg|400px|thumb|right|&lt;br /&gt;
Рис. 1 - Расположение  работ.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
В серой области могут быть прерывания.&lt;br /&gt;
]]&lt;br /&gt;
Корректность алгоритма очевидна.&lt;br /&gt;
Докажем оптимальность.&lt;br /&gt;
&lt;br /&gt;
Пусть, для опеределенности &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим станок на котором достигается &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
*Если это &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;, то оптимальность очевидна &amp;lt;tex&amp;gt;(C_{max} \geqslant \sum\limits_{i \in G_{1}} p_{i1})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Иначе &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; достигается на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда либо &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний и оптимальность очевидна.&lt;br /&gt;
Или есть прерывания.&lt;br /&gt;
Тогда целевая функция равна ответу задачи [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для работ &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt;, который оптимален.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Время работы алгоритма равно времени работы алгоритма  [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]], то есть &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 179 {{---}} 180 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54057</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54057"/>
				<updated>2016-05-17T17:03:29Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Существование решения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за '''тайм-слот''' &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного [[Основные_определения_теории_графов|графа]] минимальным &lt;br /&gt;
количеством [[Паросочетания:_основные_определения,_теорема_о_максимальном_паросочетании_и_дополняющих_цепях|паросочетаний]].&lt;br /&gt;
&lt;br /&gt;
Определим &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; как максимальное число работ, которые можно успеть выполнить.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Существование решения===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Opij1di|&amp;lt;tex&amp;gt;O \mid p_{ij} = 1, d_i \mid - &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54056</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54056"/>
				<updated>2016-05-17T17:02:42Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за '''тайм-слот''' &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного [[Основные_определения_теории_графов|графа]] минимальным &lt;br /&gt;
количеством [[Паросочетания:_основные_определения,_теорема_о_максимальном_паросочетании_и_дополняющих_цепях|паросочетаний]].&lt;br /&gt;
&lt;br /&gt;
Определим &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; как максимальное число работ, которые можно успеть выполнить.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Существование решения===&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Opij1di|&amp;lt;tex&amp;gt;O \mid p_{ij} = 1, d_i \mid - &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54054</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54054"/>
				<updated>2016-05-17T16:47:27Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Существование решения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Существование решения===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за '''тайм-слот''' &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного [[Основные_определения_теории_графов|графа]] минимальным &lt;br /&gt;
количеством [[Паросочетания:_основные_определения,_теорема_о_максимальном_паросочетании_и_дополняющих_цепях|паросочетаний]].&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Opij1di|&amp;lt;tex&amp;gt;O \mid p_{ij} = 1, d_i \mid - &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54052</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54052"/>
				<updated>2016-05-17T16:34:21Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Оценка сложности алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Существование решения===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за '''тайм-слот''' &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Opij1di|&amp;lt;tex&amp;gt;O \mid p_{ij} = 1, d_i \mid - &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54051</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54051"/>
				<updated>2016-05-17T16:32:24Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Доказательство корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Существование решения===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за '''тайм-слот''' &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54050</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54050"/>
				<updated>2016-05-17T16:30:45Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Доказательство корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за '''тайм-слот''' &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54049</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54049"/>
				<updated>2016-05-17T16:30:13Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Доказательство корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за '''тайм-слот t''' множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54048</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54048"/>
				<updated>2016-05-17T16:29:37Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за ''тайм-слот t'' множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54046</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54046"/>
				<updated>2016-05-17T16:20:25Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за ''тайм-слот t'' множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54045</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54045"/>
				<updated>2016-05-17T16:18:52Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за ''тайм-слот t'' множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54043</id>
		<title>Opi1sumu</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Opi1sumu&amp;diff=54043"/>
				<updated>2016-05-17T16:13:24Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Дано &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; одинаковых станков, которые работают параллельно и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ, котороые необходимо выполнить в произвольном порядке на всех станках. Время выполнения каждой работы на любом станке одинаково и равно одному. Для каждой работы известно время, до которого её необходимо выполнить. Необходимо успеть выполнить как можно больше работ. }}&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
Отсортируем работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Если в оптимальном расписании можно сделать &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, то можно сделать первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
|proof=Пусть в оптимальном расписании были сделаны работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;. Докажем, что существует &lt;br /&gt;
оптимальное расписание, в котором сделаны работы &amp;lt;tex&amp;gt;1, 2, \ldots, k&amp;lt;/tex&amp;gt;. Пусть работы &amp;lt;tex&amp;gt;i_1, i_2, \ldots, i_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
тоже отсортированы в порядке неубывания дедлайна. Тогда &amp;lt;tex&amp;gt;d_{i1} \leqslant d_1, d_{i2}\leqslant d_2, \ldots, d_{ik}\leqslant d_{k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, если заменить во всём расписании работу &amp;lt;tex&amp;gt;i_j&amp;lt;/tex&amp;gt; на работу &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, то она, тем более, будет выполнена.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Обозначим за ''тайм-слот t'' множество из не более, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; различных чисел {{---}} &lt;br /&gt;
номера работ, которые мы хотим выполнить в момент времени &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Введем тайм-слот для каждого момента времени от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;d_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Каждую работу будем пытаться сделать как можно позже. Будем рассматривать работы в порядке невозрастания дедлайнов. &lt;br /&gt;
&amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ю работу попытаемся добавить в тайм-слоты с номерами от &amp;lt;tex&amp;gt;d_i - m + 1&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
После добавления некоторые тайм-слоты могли переполниться (тайм-слот переполнился, если в нём уже находилось&lt;br /&gt;
&amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ, и в него добавили &amp;lt;tex&amp;gt;m+1&amp;lt;/tex&amp;gt;-ю). &lt;br /&gt;
Для переполнившегося тайм-слота найдём найдем самый правый левее него тайм-слот, который ещё не переполнился и перекинем работу, &lt;br /&gt;
которой там еще нет, в него. Так как в нем меньше элементов, то по принципу Дирихле, это можно сделать. &lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Следуя этому алгоритму, расписания не существует тогда и только тогда, когда&lt;br /&gt;
переполнился нулевой тайм-слот.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt;\Rightarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Расписания не существует, а значит, никакой алгоритм его не найдет.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\Leftarrow&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем понятие ''фронта'' расписания. ''Фронтом'' назовем вектор размеров тайм-слотов. Заметим, что от того, в каком порядке происходят перебрасывания из переполнившихся тайм-слотов, итоговый фронт не зависит. Поэтому, если мы сначала положим все работы в тайм-слоты, игнорируя ограничение на их размер, а потом в каком-то порядке перекинем, итоговый фронт окажется тем же. В случае, если при построении тайм-слотов игнорировалось ограничение на их размер, ни одну единицу работы нельзя назначить позже.&lt;br /&gt;
&lt;br /&gt;
Будем также рассматривать тайм-слоты без номеров работ: в каждом тайм-слоте просто лежит сколько-то единиц работ. От этого итоговый фронт также не изменится. Заметим, что если нельзя составить корректную в плане наполненности конфигурацию тайм-слотов при данном ослаблении, то нельзя это сделать и в случае существования номера у каждой единицы работы. Будем рассматривать тайм-слоты по убыванию времени с &amp;lt;tex&amp;gt;d_1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В каждый момент времени будем хранить сколько работ ''необходимо'' перекинуть на более ранние тайм-слоты. Изначально это число равно нулю.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим очередной тайм-слот. Пусть в нем занято &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; ячеек из &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а также есть еще &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; нераспределяемых позже единиц работы. Здесь возможны два случая:&lt;br /&gt;
* &amp;lt;tex&amp;gt;h +  a &amp;gt; m&amp;lt;/tex&amp;gt;. В этом случае, так как более &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; единиц работы сейчас выполнить нельзя, а также ничего нельзя назначить позже, то оказывается, что невыполняемых сейчас или позже работ стало &amp;lt;tex&amp;gt;h + a - m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Если &amp;lt;tex&amp;gt;h + a \leqslant m&amp;lt;/tex&amp;gt;. Здесь можно назначить все нераспределяемые позже работы на это время, и сбросить их счетчик.&lt;br /&gt;
&lt;br /&gt;
Так как и этот, и изучаемый алгоритм получают в итоге одинаковый фронт, а в этом мы вышли из нулевого времени, а невыполненные единицы работы остались, то так как распределить их никак невозможно, то не существует расписания, в котором бы выполнились все работы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Опираясь на это утверждение, можно найти максимальное количество работ, которое можно выполнить. Обозначим его за &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сведем задачу построения распинания по построенным тайм-слотам к задаче о покрытии двудольного графа минимальным &lt;br /&gt;
количеством паросочетаний.&lt;br /&gt;
&lt;br /&gt;
Построим двудольный граф. В левой доле вершинам будут соответствовать работы, в правой {{---}} времена. Соответственно, в левой доле будет &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершин, в правой {{---}} &amp;lt;tex&amp;gt;d_{max}&amp;lt;/tex&amp;gt;. Ребро между работой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и временем &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; будет, если работа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; есть в тайм-слоте &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим какое-то паросочетание &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; в этом графе. Оно соответствует корректному расписанию работ на одной машине: ни одна работа не выполняется два раза и ни в один момент времени не выполняется более одной работы.&lt;br /&gt;
&lt;br /&gt;
Тогда, если мы сможем построить множество мощности &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; такое, что каждое ребро находится хотя бы в одном из паросочетаний, то оно будет соответствовать тому, что каждая работа обработана на каждом станке, а значит, составлено корректное расписание для этих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
Достроим граф до регулярного степени &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Достраивать будем следующим образом. Каждая вершина в левой доле имеет степень &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как каждая работа представлена в &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; тайм-слотах. В правой доле степень каждой вершины не больше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, так как в тайм-слоте не может быть больше, чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; работ. Значит, в левой доле не больше вершин, чем в правой.&lt;br /&gt;
Добавим в левую долю фиктивных вершин, чтобы количества вершин в левой и правой долях сравнялись. После чего просто будем добавлять ребра между вершинами, степень которых еще меньше &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;. Для покрытия этого графа паросочетаниями воспользуемся тем фактом, что регулярный двудольный граф степени &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; можно покрыть &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; паросочетаниями. &lt;br /&gt;
&lt;br /&gt;
При помощи построения паросочетаний было построено расписание для тех &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ, которые можно успеть сделать. Так как остальные работы уже нельзя успеть, расписание для них можно составить произвольное. Например, выполнять их по очереди после выполнения первых &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; работ.&lt;br /&gt;
&lt;br /&gt;
===Оценка сложности алгоритма===&lt;br /&gt;
Рассмотрим добавление очередной работы в тайм-слоты. За &amp;lt;tex&amp;gt;O(t)&amp;lt;/tex&amp;gt; найдём переполнившийся тайм-слот и за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; перекинем из него элемент. Так как &amp;lt;tex&amp;gt;t=O(nm)&amp;lt;/tex&amp;gt;, итоговая сложность этой части {{---}} &amp;lt;tex&amp;gt;O(n^2m)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достроение графа до регулярного делается за &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E&amp;lt;/tex&amp;gt; {{---}} количество ребер в нем. Количество ребер в регулярном двудольном графе &amp;lt;tex&amp;gt;E = Vd&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; {{---}} количество вершин в одной из долей, а &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} степень. Количество вершин в правой доле {{---}} &amp;lt;tex&amp;gt;O(t) = O(nm)&amp;lt;/tex&amp;gt;. Значит граф будет построен за &amp;lt;tex&amp;gt;O(nm^2)&amp;lt;/tex&amp;gt;, так как степень каждой вершины {{---}} &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность последней фазы зависит от того, каким алгоритмом граф разбивается на паросочетания. Использовав, например, алгоритм Куна, можно добиться сложности &amp;lt;tex&amp;gt;O(m \cdot M) = O(m \cdot n^3m^3)&amp;lt;/tex&amp;gt;. Итоговая сложность алгоритма {{---}} &amp;lt;tex&amp;gt;O(n^3m^4)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 179 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54040</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54040"/>
				<updated>2016-05-17T15:56:20Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Задача Джонсона о двух станках с прерываниями F_2 \mid pmtn \mid C_{max} */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Его можно посмотреть тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
J {{---}} список работ, которые надо выполнить, &amp;lt;tex&amp;gt; \mathrm{FirstList}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{SecondList} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{FirstList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{SecondList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{FirstList} = \mathrm{FirstList} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{SecondList} = I \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = \mathrm{FirstList} \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54039</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54039"/>
				<updated>2016-05-17T15:55:33Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Задача Джонсона о двух станках с прерываниями F_2 \mid pmtn \mid C_{max} */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Его можно посмотреть тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
J {{---}} список работ, которые надо выполнить, &amp;lt;tex&amp;gt; \mathrm{FirstList}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{SecondList} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{FirstList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{SecondList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{FirstList} = \mathrm{FirstList} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{SecondList} = I \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = \mathrm{FirstList} \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше.&lt;br /&gt;
|proof = Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54038</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54038"/>
				<updated>2016-05-17T15:52:41Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Его можно посмотреть тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
J {{---}} список работ, которые надо выполнить, &amp;lt;tex&amp;gt; \mathrm{FirstList}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{SecondList} &amp;lt;/tex&amp;gt; {{---}} списки, в которые будем записывать порядок выполнения работ.&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{FirstList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{SecondList} = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{FirstList} = \mathrm{FirstList} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;\mathrm{SecondList} = I \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = \mathrm{FirstList} \cup  \mathrm{SecondList} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54036</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54036"/>
				<updated>2016-05-17T15:44:36Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Его можно посмотреть тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
    &amp;lt;tex&amp;gt; FirstList = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;SecondList = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;font color = green&amp;gt;//J - множество работ&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;FirstList = {FirstList} \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;SecondList = I \cup  SecondList &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = FirstList \cup  SecondList &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54035</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=54035"/>
				<updated>2016-05-17T15:41:27Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Его можно посмотреть тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка и будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
    &amp;lt;tex&amp;gt; Head = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;Tail = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;font color = green&amp;gt;//J - множество работ&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;Head = {Head } \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;Tail = I \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = Head \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=54034</id>
		<title>J2ni2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=54034"/>
				<updated>2016-05-17T15:23:56Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Доказательство корректности алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;J2 \mid n_i \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*Дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка.&lt;br /&gt;
*Для каждой работы известно её время выполнения на каждом станке &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Для каждой работы известна последовательность &amp;lt;tex&amp;gt;O_{i1}, \ O_{i2} \ \ldots \ O_{ik}&amp;lt;/tex&amp;gt; станков {{---}} порядок, в котором нужно выполнить работу. &lt;br /&gt;
*В каждой последовательности &amp;lt;tex&amp;gt;O_{i}&amp;lt;/tex&amp;gt; не более двух элементов.&lt;br /&gt;
Требуется минимизировать время окончания выполнения всех работ. }}&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; - первый станок. &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; - второй станок. &lt;br /&gt;
&lt;br /&gt;
Разобьем все работы на четыре множества:&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Решим задачу [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; и для &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; независимо. Получим расписание &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда оптимальное расписание для нашей задачи будет следующим:&lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Примечание: во время выполнения &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; могут возникнуть простои &lt;br /&gt;
из-за того, что работа ещё не выполнилась на предыдущем станке.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;T_{j}(x)&amp;lt;/tex&amp;gt; {{---}} время выполнения множества работ &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; на станке &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G_{j}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые нужно сделать хотя бы раз на &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;-м станке, то есть &amp;lt;tex&amp;gt;G_{1} = I_{1} \cup I_{12} \cup I_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1 &lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, обладает следующим свойством: один из станков работает без простоев.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим два случая:&lt;br /&gt;
#&amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) \geqslant T_{2}(I_{21}) &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{1} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#&amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) &amp;lt; T_{2}(I_{21}) &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{2} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
[[Файл: j2ni2cmax.jpg|400px|thumb|right|&lt;br /&gt;
Рис. 1 - Расположение  работ.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
В серой области могут быть прерывания.&lt;br /&gt;
]]&lt;br /&gt;
Корректность алгоритма очевидна.&lt;br /&gt;
Докажем оптимальность.&lt;br /&gt;
&lt;br /&gt;
Пусть, для опеределенности &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим станок на котором достигается &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
*Если это &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;, то оптимальность очевидна &amp;lt;tex&amp;gt;(C_{max} \geqslant \sum\limits_{i \in G_{1}} p_{i1})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Иначе &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; достигается на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда либо &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний и оптимальность очевидна.&lt;br /&gt;
Или есть прерывания.&lt;br /&gt;
Тогда целевая функция равна ответу задачи [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для работ &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt;, который оптимален.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Время работы алгоритма равно времени работы алгоритма  [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]], то есть &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. 179 {{---}} 180 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54013</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=54013"/>
				<updated>2016-05-16T21:28:35Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.2.png|500px|thumb|Рис. 1 - Исходная сеть]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Файл:Figure_5.9.b.png|500px|thumb|Рис. 2 - Расширение сети]]&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
===Корректность и оптимальность алгоритма===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
* &amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table align = center&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно&amp;lt;ref&amp;gt;Описано в Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 133 стр.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54010</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54010"/>
				<updated>2016-05-16T20:51:36Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая:&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;. Будем строить расписание с двух концов:&lt;br /&gt;
##*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
##*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} \leqslant b_{y}&amp;lt;/tex&amp;gt;. Сводится к первому, если поменять местами станки и соответствующие списки времён выполнения, при этом надо заново выполнить пункты 1,2 и 3. При выдаче ответа меняем станки обратно местами.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.&amp;lt;br&amp;gt;//Функция возвращает пару из расписания для первого станка и расписания для второго станка.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         ans = пара из расписания для первого станка и расписания для второго станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158{{---}}160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54009</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54009"/>
				<updated>2016-05-16T20:50:43Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая:&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;. Будем строить расписание с двух концов:&lt;br /&gt;
##*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
##*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} \leqslant b_{y}&amp;lt;/tex&amp;gt;. Сводится к первому, если поменять местами станки и соответствующие списки времён выполнения, при этом надо заново выполнить пункты 1,2 и 3. При выдаче ответа меняем станки обратно местами.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.&amp;lt;br&amp;gt;//Функция возвращает пару из расписания для первого станка и расписания для второго станка.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         ans = пара из расписания для первого станка и расписания для второго станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158-160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54008</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54008"/>
				<updated>2016-05-16T20:48:49Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая:&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;. Будем строить расписание с двух концов:&lt;br /&gt;
##*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
##*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} \leqslant b_{y}&amp;lt;/tex&amp;gt;. Сводится к первому, если поменять местами станки и соответствующие списки времён выполнения, при этом надо заново выполнить пункты 1,2 и 3. При выдаче ответа меняем станки обратно местами.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.&amp;lt;br&amp;gt;//Функция возвращает пару из расписания для первого станка и расписания для второго станка.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} \geqslant b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         ans = пара из расписания для первого станка и расписания для второго станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158-160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54007</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54007"/>
				<updated>2016-05-16T20:46:48Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая:&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;. Будем строить расписание с двух концов:&lt;br /&gt;
##*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
##*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} \leqslant b_{y}&amp;lt;/tex&amp;gt;. Сводится к первому, если поменять местами станки, при этом надо заново выполнить пункты 1,2 и 3. При выдаче ответа меняем станки обратно местами.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.&amp;lt;br&amp;gt;//Функция возвращает пару из расписания для первого станка и расписания для второго станка.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} \geqslant b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         ans = пара из расписания для первого станка и расписания для второго станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158-160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54006</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54006"/>
				<updated>2016-05-16T20:44:49Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая:&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt;. Будем строить расписание с двух концов:&lt;br /&gt;
##*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
##*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
## &amp;lt;tex&amp;gt;a_{x} \leqslant b_{y}&amp;lt;/tex&amp;gt;. Сводится к первому, если поменять местами станки,при этом надо заново выполнить пункты 1-3. При выдаче ответа ответа меняем станки обратно местами.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.&amp;lt;br&amp;gt;//Функция возвращает пару из расписания для первого станка и расписания для второго станка.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} \geqslant b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         ans = пара из расписания для первого станка и расписания для второго станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158-160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54004</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54004"/>
				<updated>2016-05-16T20:20:55Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая. Первый случай, когда &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt; (он показан на рисунке ниже). Будем строить расписание с двух концов:&lt;br /&gt;
#*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Второй случай сводится к первому: все работы и станки меняются местами, и решается задача для первого случая.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.&amp;lt;br&amp;gt;//Функция возвращает пару из расписания для первого станка и расписания для второго станка.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} \geqslant b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         ans = пара из расписания для первого станка и расписания для второго станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158-160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54003</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54003"/>
				<updated>2016-05-16T20:15:47Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая. Первый случай, когда &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt; (он показан на рисунке ниже). Будем строить расписание с двух концов:&lt;br /&gt;
#*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Второй случай сводится к первому: все работы и станки меняются местами, и решается задача для первого случая.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''pair&amp;lt;int[n], int[n]&amp;gt;''' ans&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} \geqslant b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
         Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
         От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
         ans = пара из расписания для первого станка и расписания для воторого станка &lt;br /&gt;
         '''return''' ans&lt;br /&gt;
     '''else'''&lt;br /&gt;
         ans = scheduling(b, a)&lt;br /&gt;
         Меняем местами расписания для станков в ans&lt;br /&gt;
         '''return''' ans    &lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158-160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54002</id>
		<title>O2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=O2Cmax&amp;diff=54002"/>
				<updated>2016-05-16T20:02:55Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка,&lt;br /&gt;
*для каждой работы известно её время выполнения на каждом станке.&lt;br /&gt;
Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}}&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; {{---}} время выполнения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой работы на первом станке, а &amp;lt;tex&amp;gt;b_{i}&amp;lt;/tex&amp;gt; {{---}} на втором.&amp;lt;br/&amp;gt;&lt;br /&gt;
#Разобьём все работы на два множества: &amp;lt;tex&amp;gt;I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J = \{i \mid a_{i} &amp;gt; b_{i}; i = 1, \dots, n\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Найдем такие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Построим оптимальное значение целевой функции: &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \ \sum \limits_{i = 1}^{n} b_i,\ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Рассмотрим два случая. Первый случай, когда &amp;lt;tex&amp;gt;a_{x} &amp;gt; b_{y}&amp;lt;/tex&amp;gt; (он показан на рисунке ниже). Будем строить расписание с двух концов:&lt;br /&gt;
#*Строим расписание слева: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;, а на втором выполняем первой работу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#*Теперь, упираясь в правую границу, равную &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;, можно построить расписание справа: выполняем на первом станке все работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а для второго выполняем работы из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:Второй случай сводится к первому: все работы и станки меняются местами, и решается задача для первого случая.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Picture2.gif‎|500px|center]]&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.&amp;lt;br/&amp;gt;&lt;br /&gt;
Первое утверждение вытекает из того, что мы строили расписание, опираясь на &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;. Из построения &amp;lt;tex&amp;gt;C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}&amp;lt;/tex&amp;gt;, следовательно на каждом станке в любой момент времени выполняется не более одной работы.&amp;lt;br/&amp;gt;&lt;br /&gt;
Докажем теперь второе утверждение. У нас имеется 3 блока работ: &amp;lt;tex&amp;gt; I \setminus \{x\}, \{x\}, J&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для блока &amp;lt;tex&amp;gt; \{x\}&amp;lt;/tex&amp;gt; это следует из того, что &amp;lt;tex&amp;gt; C_{max} \geqslant a_{x}+b_{x}&amp;lt;/tex&amp;gt;, а работа &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; выполняется с разных концов станков. Получили, что отрезки выполнения работы &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; на разных станках не пересекаются.&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt; I \setminus \{x\}&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^k b_{i} = \sum \limits_{i = 1}^{k - 1} b_{i} + b_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на первом станке во время данного блока.&amp;lt;br&amp;gt;Это неравенство следует из выбора &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&amp;lt;br&amp;gt;Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&amp;lt;br&amp;gt;&lt;br /&gt;
# Покажем, что любая работа из &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:&amp;lt;br&amp;gt;&amp;lt;tex&amp;gt;\sum \limits_{i = 1}^k b_{i} \leqslant \sum \limits_{i = 1}^k a_{i} \leqslant \sum \limits_{i = 1}^{k - 1} a_{i} + a_{x}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;1 \dots k&amp;lt;/tex&amp;gt; {{---}} это работы, выполняемые на втором станке во время данного блока.&lt;br /&gt;
Это неравенство следует из выбора &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; и из того, что &amp;lt;tex&amp;gt;a_{x} \geqslant a_{i}, \forall i \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.&lt;br /&gt;
&lt;br /&gt;
Итого мы доказали корректность.&amp;lt;br/&amp;gt;&lt;br /&gt;
Оптимальность вытекает из того, что &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; не может быть меньше &amp;lt;tex&amp;gt;\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}&amp;lt;/tex&amp;gt;, а из построения оно равно максимуму из этих значений.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 function scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair&amp;lt;int[n], int[n]&amp;gt;'''&lt;br /&gt;
     &amp;lt;tex&amp;gt;I = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;J = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     &amp;lt;tex&amp;gt;C_{max} = \max \{\sum \limits_{i = 1}^{n} a_i, \  \sum \limits_{i = 1}^{n} b_i, \  \max \limits_{i = 1}^{n}\{a_i + b_{i}\}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''for''' &amp;lt;tex&amp;gt;i = 1&amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;a_{i} \leqslant b_{i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           &amp;lt;tex&amp;gt; I = I \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''else'''&lt;br /&gt;
           &amp;lt;tex&amp;gt; J = J \cup \{i\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a_{x} = \max \limits_{i \in I} \{a_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Найти &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{y} = \max \limits_{i \in J} \{b_{i}\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''if''' &amp;lt;tex&amp;gt;a_{x} &amp;lt; b_{y}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        Поменять местами первый и второй станок&lt;br /&gt;
        Пересчитать &amp;lt;tex&amp;gt;I, J, x&amp;lt;/tex&amp;gt;&lt;br /&gt;
        Запомнить, что поменяли&lt;br /&gt;
   &lt;br /&gt;
     Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
     Начиная с &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;I \setminus \{x\}&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
     От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на первом станке расставляем расписание для &amp;lt;tex&amp;gt;\{x\}&amp;lt;/tex&amp;gt;, затем для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&lt;br /&gt;
     От правой границы {{---}} &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; на втором станке расставляем расписание для &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
       '''if''' станки меняли местами&lt;br /&gt;
        поменять их обратно&lt;br /&gt;
&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Каждое из множеств в сумме содержит &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций, чтобы составить расписание для каждой работы из множества нам потребуется так же &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Получаем сложность алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158-160 ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53977</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53977"/>
				<updated>2016-05-15T23:30:23Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Время работы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Figure_5.2.png|400px|thumb|right|Рис. 1 - Исходная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
[[Файл:Figure_5.9.b.png|500px|thumb|right|Рис. 2 - Расширение сети]]&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно&amp;lt;ref&amp;gt;Описано в Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. {{---}} 133 стр.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53976</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53976"/>
				<updated>2016-05-15T23:28:16Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Figure_5.2.png|400px|thumb|right|Рис. 1 - Исходная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
[[Файл:Figure_5.9.b.png|500px|thumb|right|Рис. 2 - Расширение сети]]&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно. Лабетоль (Labetoulle J.), Лаулер (Lawler E.L.), Ленстра (Lenstra. J.K.), и Ринной Кан (Rinnooy Kan A.H.G.) разработали алгоритм работающий за &amp;lt;tex&amp;gt; O(n \log(n) + mn) &amp;lt;/tex&amp;gt; специально для этого случая.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53975</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53975"/>
				<updated>2016-05-15T23:26:17Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Figure_5.2.png|400px|thumb|right|Рис. 1 - Исходная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
[[Файл:Figure_5.9.b.png|500px|thumb|right|Рис. 2 - Расширение сети]]&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно. Лабетоль (Labetoulle J.), Лаулер (Lawler E.L.), Ленстра (Lenstra. J.K.), и Ринной Кан (Rinnooy Kan A.H.G.) разработали алгоритм работающий за &amp;lt;tex&amp;gt; O(n \log(n) + mn) &amp;lt;/tex&amp;gt; специально для этого случая.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. 129 {{---}} 133 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53974</id>
		<title>QpmtnriLmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=QpmtnriLmax&amp;diff=53974"/>
				<updated>2016-05-15T23:24:20Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot;&amp;gt;Q \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу на нахождение расписания:&lt;br /&gt;
# У нас есть несколько станков, работающих параллельно. У станков могут быть разные скорости выполнения работ.&lt;br /&gt;
# Есть несколько заданий, каждое имеет своё время появления &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и время окончания &amp;lt;tex&amp;gt;d_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Работа может быть прервана в любой момент и продолжена позже на любой машине.&lt;br /&gt;
Требуется минимизировать максимальное опоздание &amp;lt;tex&amp;gt;L_{max} = \max\limits_i \{C_i - d_i\}&amp;lt;/tex&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Figure_5.2.png|400px|thumb|right|Рис. 1 - Исходная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
===Алгоритм решения===&lt;br /&gt;
[[Файл:Figure_5.9.b.png|500px|thumb|right|Рис. 2 - Расширение сети]]&lt;br /&gt;
&lt;br /&gt;
Как в [[PpmtnriLmax|задаче]] &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt; применим метод [[Вещественный_двоичный_поиск|двоичного поиска]] и сведем задачу к &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt;. Для существования расписания с &amp;lt;tex&amp;gt; L_{max} \leqslant L^* &amp;lt;/tex&amp;gt; требуется, чтобы у работы с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; выполнялось &amp;lt;tex&amp;gt; C_i - d_i \leqslant L^* &amp;lt;/tex&amp;gt;, что эквивалентно &amp;lt;tex&amp;gt; C_i \leqslant d_i + L^* &amp;lt;/tex&amp;gt;. Опишем алгоритм решения &amp;lt;tex&amp;gt; Q \mid pmtn, r_i, d_i \mid - &amp;lt;/tex&amp;gt; при помощи сведения к задаче поиска [[Определение_сети,_потока|максимального потока]].&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; t_1 \leqslant t_2 \leqslant ... \leqslant t_r &amp;lt;/tex&amp;gt; {{---}} упорядоченная последовательность всех значений &amp;lt;tex&amp;gt;r_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;d_i + L^*&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Определим интервалы на исходной сети (Рис. 1) &amp;lt;tex&amp;gt; I_K := [t_{K-1}, t_K], \  T_K = t_K-t_{K-−1} &amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt; K = 2,..., r &amp;lt;/tex&amp;gt;. Cчитаем, что станки занумерованы в порядке невозрастания скоростей &amp;lt;tex&amp;gt; s_1 \geqslant s_2 \geqslant . . . \geqslant s_m &amp;lt;/tex&amp;gt; (также считаем &amp;lt;tex&amp;gt;s_{m+1} = 0&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Искомая сеть строится с помощью расширения сети из задачи &amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt; J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; набор предшественников узла &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;, тогда замененная нами подсеть определяется как &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расширение сети показано на Рис. 2.&lt;br /&gt;
&lt;br /&gt;
Расширенная подсеть строится путем добавления к вершинам &amp;lt;tex&amp;gt; I_K, J_{i_1}, J_{i_2}, . . . , J_{i_s} &amp;lt;/tex&amp;gt; вершин &amp;lt;tex&amp;gt;(K, 1), (K, 2), . . . (K, m) &amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;j = 1,..., m &amp;lt;/tex&amp;gt;, есть дуги от &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; j(s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;\nu = 1,. . . , s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;j = 1,. . ., m&amp;lt;/tex&amp;gt; существует дуга из &amp;lt;tex&amp;gt;J_{i_\nu}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;(K, J)&amp;lt;/tex&amp;gt; с пропускной способностью &amp;lt;tex&amp;gt; (s_j - s_{j+1}) T_K &amp;lt;/tex&amp;gt;. Это выполняется для каждой вершины &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Кроме того, мы сохраняем дуги из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt; и дуги из &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; пропускной способностью &amp;lt;tex&amp;gt;S_mT_K&amp;lt;/tex&amp;gt; (Рис. 1).&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Следующие утверждения эквивалентны:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; Существует допустимое расписание.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; В расширенной сети существует поток от &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; со значением &amp;lt;tex&amp;gt;\sum\limits_{i=1}^n p_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|proof=&amp;lt;tex&amp;gt;(b) \Rightarrow (a):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Рассмотрим в расширенной сети поток величиной &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n {p_i}&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; общий поток, который идет от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^n \sum\limits_{K = 2}^r x_{iK} = \sum\limits_{i = 1}^n p_i&amp;lt;/tex&amp;gt;. Достаточно показать, что для каждого подмножества &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; выполняется&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; ,где &amp;lt;tex&amp;gt;h(A) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
 S_{|A|}, &amp;amp; \text{if }|A| \leqslant m \\&lt;br /&gt;
 S_m, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это означает, что условие &amp;lt;tex&amp;gt;\sum\limits_{i \in A} p_i \leqslant Th(A), \forall A \subseteq \{ 1, ... , n \}&amp;lt;/tex&amp;gt; выполняется  и требования к обработке &amp;lt;tex&amp;gt;x_{1K}, . . . , x_{nK}&amp;lt;/tex&amp;gt; могут быть запланированы как &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt;. Рассмотрим подсеть в расширенной сети в подмножестве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и соответствующие части потока. Фрагмент частичного потока, который проходит через &amp;lt;tex&amp;gt;(K, j)&amp;lt;/tex&amp;gt; ограничен&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min \{ j(s_j −- s_{j + 1})T_K, |A|(s_j - s_{j+1})T_K \} = T_K(s_j - s_{j+1}) \min \{ j, |A| \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы имеем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \geqslant T_K \sum\limits_{j = 1}^m(s_j −- s_{j+1}) \min \{ j, |A| \} = T_Kh(A)&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То, что равенство &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt; справедливо, может рассматриваться как следствие. Если &amp;lt;tex&amp;gt;|A| &amp;gt; m&amp;lt;/tex&amp;gt;, то&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - 3s_4 + ... + ms_s - ms_{m+1} =\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;S_m = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В противном случае&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{j = 1} \min \{ j, |A| \}(s_j - s_{j + 1}) = s_1 - s_2 + 2s_2 - 2s_3 + 3s_3 - ... + (|A| - 1)s_{|A| - 1} -\ &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;(|A| - 1)s_{|A|} + |A|(s_{|A|} - s_{|A| - 1} - ... - s_m + s_m - s_{m + 1}) = S_{|A|} = h(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(a) \Rightarrow (b):&amp;lt;/tex&amp;gt;&lt;br /&gt;
Предположим, что допустимое расписание существует. Для &amp;lt;tex&amp;gt;i = 1, ... , n &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; пусть &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; является &amp;quot;объемом работ&amp;quot;, который будет выполняться в интервале &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; в соответствии с нашим возможным расписанием. Тогда для всех &amp;lt;tex&amp;gt;K = 2, ..., r&amp;lt;/tex&amp;gt; и произвольных наборов &amp;lt;tex&amp;gt;A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt;, неравенство&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_Kh(A)&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выполняется. Кроме того, для &amp;lt;tex&amp;gt;i = 1, . . . , n&amp;lt;/tex&amp;gt; у нас &amp;lt;tex&amp;gt;p_i = \sum\limits_{K = 2}^r s_{iK}&amp;lt;/tex&amp;gt;. Остается показать, что можно отправить &amp;lt;tex&amp;gt;x_{iK}&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;J_i&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(i = 1, . . . , n; K = 2, . . . , r)&amp;lt;/tex&amp;gt; в расширенной сети. Такой поток существует, если &amp;lt;tex&amp;gt;\forall A \subseteq \{ 1, . . . , n \}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K = 2, . . . , r&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK}&amp;lt;/tex&amp;gt; ограничено величиной минимального разреза части сети с истоками &amp;lt;tex&amp;gt;J_i(i \in A)&amp;lt;/tex&amp;gt; и стоком &amp;lt;tex&amp;gt;I_K&amp;lt;/tex&amp;gt;. Тем не менее, это значение&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T_K\sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Используя &amp;lt;tex&amp;gt;(**)&amp;lt;/tex&amp;gt; и правую часть &amp;lt;tex&amp;gt;(*)&amp;lt;/tex&amp;gt;, получаем&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum\limits_{i \in A} x_{iK} \leqslant T_K h(A) = T_K \sum\limits_{j = 1}^m \min \{ j, |A| \}(s_j - s_{j+1})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что и является искомым неравенством.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
&lt;br /&gt;
Работа с максимальным потоком в расширенной сети занимает &amp;lt;tex&amp;gt;O (m n^3)&amp;lt;/tex&amp;gt; шагов, проверка может быть сделана с такой же скоростью. Для решения &amp;lt;tex&amp;gt;Q \mid pmtn; r_{i} \mid L_{max}&amp;lt;/tex&amp;gt; мы используем бинарный поиск, а значит, получаем алгоритм с &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;-приближенной  сложностью &amp;lt;tex&amp;gt;O (mn^3(\log(n) + \log(1 / \varepsilon) + \log(\max\limits_{i=1}^{n} p_i)) &amp;lt;/tex&amp;gt;, потому как &amp;lt;tex&amp;gt;L_{max}&amp;lt;/tex&amp;gt;, ограничен &amp;lt;tex&amp;gt;n \max\limits_{i=1}^{n}p_i&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;s_1 = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Задача &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid C_{max}&amp;lt;/tex&amp;gt; представляет собой частный случай &amp;lt;tex&amp;gt;Q \mid pmtn; r_i \mid L_{max}&amp;lt;/tex&amp;gt;, и может быть решена более эффективно. Лабетоль (Labetoulle J.), Лаулер (Lawler E.L.), Ленстра (Lenstra. J.K.), и Ринной Кан (Rinnooy Kan A.H.G.) разработали алгоритм работающий за &amp;lt;tex&amp;gt; O(n \log(n) + mn) &amp;lt;/tex&amp;gt; специально для этого случая.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. 137 {{---}} 139 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=53973</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=53973"/>
				<updated>2016-05-15T23:19:10Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Задача Джонсона о двух станках F_2 \mid \mid C_{max} */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства&amp;lt;ref&amp;gt; Его можно посмотреть тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка. Будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
    &amp;lt;tex&amp;gt; Head = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;Tail = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;font color = green&amp;gt;//J - множество работ&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;Head = {Head } \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;Tail = I \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = Head \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=53972</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=53972"/>
				<updated>2016-05-15T23:18:42Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются [[NP | NP-трудными]].&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства &amp;lt;ref&amp;gt; Его можно посмотреть тут [http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
===Алгоритм===&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка. Будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
    &amp;lt;tex&amp;gt; Head = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;Tail = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;font color = green&amp;gt;//J - множество работ&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;\min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;Head = {Head } \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;Tail = I \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = Head \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=53971</id>
		<title>Flow shop</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Flow_shop&amp;diff=53971"/>
				<updated>2016-05-15T23:12:05Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Рассмотрим пример:  &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; машин. В начальный момент времени мы можем начать обрабатывать любую работу на первой машине. В следующий момент на первой машине можно обрабатывать следующую работу, а на второй перейдёт предыдущая работа с первой машины, и так далее. Таким образом, на выполнение всех работ у нас уйдёт &amp;lt;tex&amp;gt;n + m - 1&amp;lt;/tex&amp;gt; единиц времени. Проиллюстрируем это диаграммой Гантта для случая &amp;lt;tex&amp;gt;n = 6, m = 5&amp;lt;/tex&amp;gt;:&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot; style=&amp;quot;width: 55%; height: 200px&amp;quot;&lt;br /&gt;
! !!0!!1!!2!!3!!5!!6!!7!!8!!9!!10&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|—&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
!&amp;lt;tex&amp;gt;M_5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|—&lt;br /&gt;
|1&lt;br /&gt;
|2&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Заметим, что в данном случае &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt; может быть равно не только единице, но и любой константе.&lt;br /&gt;
 &lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = Любая задача вида &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; сводится к соответствующей задаче вида &amp;lt;tex&amp;gt;1 \mid p_{ij} = 1 \mid ?&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = &lt;br /&gt;
Поскольку работа всегда заканчивает выполняться на последней машине, нас интересуют только времена завершения работ на последней машине. Также очевидно, что последняя машина может начать работать только в момент времени &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Оказывается, что любое решение задачи &amp;lt;tex&amp;gt; 1 \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt; с дедлайнами, уменьшенными на &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt; можно преобразовать в оптимальное расписание для задачи &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid ? &amp;lt;/tex&amp;gt;. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Возьмем оптимальное расписание для соответствующей задачи с одним станком, выполним работы в этом порядке на первой машине, затем на второй машине, начиная с момента времени &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, и так далее, до выполнения на последней машине, начиная с &amp;lt;tex&amp;gt; m - 1 &amp;lt;/tex&amp;gt;. Это расписание корректно и соблюдает все дедлайны. Поскольку целевая функция совпадает с соответствующей функцией для задачи на одном станке, оно оптимально и для данной задачи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Примером применения этого утверждения может служить следующая [[Fpij1sumwu|задача: &amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_iu_i&amp;lt;/tex&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
Задачи с произвольными временами выполнения работ почти все являются NP-трудными.&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Это единственная из flow shop задач с произвольными временами выполнения работ, которая решается за полиномиальное время.&lt;br /&gt;
&lt;br /&gt;
Приведём здесь решение задачи без доказательства &amp;lt;ref&amp;gt; Его можно посмотреть тут[http://books.google.ru/books?id=FrUytMqlCv8C&amp;amp;printsec=frontcover&amp;amp;dq=scheduling+algorithms&amp;amp;hl=ru&amp;amp;sa=X&amp;amp;ei=0MPMT4HqKYSk4gSBm6gp&amp;amp;sqi=2&amp;amp;ved=0CDEQ6AEwAA#v=onepage&amp;amp;q=scheduling%20algorithms&amp;amp;f=false Scheduling Algorithms, Peter Brucker] &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оптимальное расписание для первой и второй машины будет совпадать. Таким образом, нам требуется найти порядок, в котором будут выполняться работы на каждой машине.&lt;br /&gt;
&lt;br /&gt;
Алгоритм такой: возьмём два пустых списка. Будем рассматривать работы в порядке возрастания &amp;lt;tex&amp;gt;min(p_1, p_2)&amp;lt;/tex&amp;gt;, то есть, минимума из времён выполнения данной работы на первой и второй машине. Если у работы &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;, то добавим её в конец первого списка. В противном случае, добавим её в начало второго списка. Итоговое расписание — это конкатенация первого и второго списков.&lt;br /&gt;
&lt;br /&gt;
Псевдокод:&lt;br /&gt;
    &amp;lt;tex&amp;gt; Head = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;Tail = \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;font color = green&amp;gt;//J - множество работ&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''while''' J &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         I &amp;lt;tex&amp;gt; = &amp;lt;/tex&amp;gt; работа с минимальным значением &amp;lt;tex&amp;gt;min(p_1, p_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''if''' &amp;lt;tex&amp;gt;p_1 \leqslant p_2&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;Head = {Head } \cup  I &amp;lt;/tex&amp;gt;&lt;br /&gt;
         '''else''' &lt;br /&gt;
             &amp;lt;tex&amp;gt;Tail = I \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
         &amp;lt;tex&amp;gt;J = J \setminus I &amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathrm{Result} = Head \cup  Tail &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача Джонсона о двух станках с прерываниями &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Оптимальное решение этой задачи совпадает с решением задачи &amp;lt;tex&amp;gt;F_2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;, приведённой выше. Докажем это.&lt;br /&gt;
&lt;br /&gt;
Пусть у нас есть оптимальное расписание для задачи &amp;lt;tex&amp;gt;F_2 \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;. Покажем, что его за конечное число шагов можно преобразовать к расписанию без прерываний, не изменив при это значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Рассмотрим первую машину. Допустим, что некоторая работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; выполняется в &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; или более разных промежутка времени. Тогда передвинем более ранний промежуток вправо по оси времени так, чтоб он заканчивался в тот момент, когда начинается второй промежуток, при этом работы, которые были между этими двумя промежутками, сдвинем влево на длину первого промежутка. Расписание при этом осталось корректным, так как работы на машинах по-прежнему не пересекаются, и каждая работа на второй машине делается после того, как она сделана на первой: работа &amp;lt;tex&amp;gt; J &amp;lt;/tex&amp;gt; может начать выполняться на второй машине только после того, как она целиком выполнится на первой, то есть уже после конца второго промежутка; а время окончания выполнения остальных работ на первой машине неувеличилось.&lt;br /&gt;
Важно, что подобная операция не увеличивает &amp;lt;tex&amp;gt; C_{max} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять эту операцию до тех пор, пока на первой машине все работы не станут выполняться без прерываний. Так как количество прерываний конечно, а такая операция уменьшает их количество на один, этот процесс конечен.&lt;br /&gt;
&lt;br /&gt;
Теперь избавимся от прерываний на второй машине. Точно так же рассмотрим работу, разбитую на два или более промежутка. Передвинем более поздний промежуток к концу более раннего, а работы между ними сдвинем вправо. Доказательство корректности измененного расписания аналогично доказательству для первой машины. Будем повторять данную операцию, пока на второй машине присутствуют прерывания.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили корректное расписание без прерываний, не изменив при этом значение &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt;, что и требовалось доказать.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i u_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==Примeчания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=53970</id>
		<title>J2ni2Cmax</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=J2ni2Cmax&amp;diff=53970"/>
				<updated>2016-05-15T23:11:09Z</updated>
		
		<summary type="html">&lt;p&gt;Zemskovk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = 200&amp;gt;J2 \mid n_i \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=Рассмотрим задачу:&lt;br /&gt;
*Дано &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; работ и &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; станка.&lt;br /&gt;
*Для каждой работы известно её время выполнения на каждом станке &amp;lt;tex&amp;gt;p_{ij}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Для каждой работы известна последовательность &amp;lt;tex&amp;gt;O_{i1}, \ O_{i2} \ \ldots \ O_{ik}&amp;lt;/tex&amp;gt; станков {{---}} порядок, в котором нужно выполнить работу. &lt;br /&gt;
*В каждой последовательности &amp;lt;tex&amp;gt;O_{i}&amp;lt;/tex&amp;gt; не более двух элементов.&lt;br /&gt;
Требуется минимизировать время окончания выполнения всех работ. }}&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; - первый станок. &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; - второй станок. &lt;br /&gt;
&lt;br /&gt;
Разобьем все работы на четыре множества:&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться только на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые должны выполниться сначала на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; затем на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Решим задачу [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; и для &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; независимо. Получим расписание &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда оптимальное расписание для нашей задачи будет следующим:&lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* Расписание &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;: сначала &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; в соответсвии с расписанием &amp;lt;tex&amp;gt;S_{21}&amp;lt;/tex&amp;gt;. Затем &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; в произвольном порядке. Затем &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; в соответсвии с &amp;lt;tex&amp;gt;S_{12}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Примечание: во время выполнения &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; могут возникнуть простои &lt;br /&gt;
из-за того, что работа ещё не выполнилась на предыдущем станке.&lt;br /&gt;
&lt;br /&gt;
==Доказательство корректности алгоритма==&lt;br /&gt;
&amp;lt;tex&amp;gt;T_{j}(x)&amp;lt;/tex&amp;gt; {{---}} время выполнения множества работ &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; на станке &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;G_{j}&amp;lt;/tex&amp;gt; {{---}} множество всех работ, которые нужно сделать хотя бы раз на &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;-м станке, то есть &amp;lt;tex&amp;gt;G_{1} = I_{1} \cup I_{12} \cup I_{21}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1 &lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, обладает следующим свойством: один из станков работает без простоев.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим два случая:&lt;br /&gt;
*&amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) \geqslant T_{2}(I_{21}) &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{1}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{1} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
*Иначе &amp;lt;tex&amp;gt;T_{1}(I_{12}) + T_{1}(I_{1}) &amp;lt; T_{2}(I_{21}) &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний, т.к к моменту завершения выполнения &amp;lt;tex&amp;gt;I_{2}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; M_{2} &amp;lt;/tex&amp;gt; все работы &amp;lt;tex&amp;gt;I_{12}&amp;lt;/tex&amp;gt; выполнены на &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Расписание, построенное данным алгоритмом, является корректным и оптимальным.&lt;br /&gt;
|proof=&lt;br /&gt;
[[Файл: j2ni2cmax.jpg|400px|thumb|right|&lt;br /&gt;
Рис. 1 - Расположение  работ.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
В серой области могут быть прерывания.&lt;br /&gt;
]]&lt;br /&gt;
Корректность алгоритма очевидна.&lt;br /&gt;
Докажем оптимальность.&lt;br /&gt;
&lt;br /&gt;
Пусть, для опеределенности &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt; работает без прерываний.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим станок на котором достигается &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; . &lt;br /&gt;
*Если это &amp;lt;tex&amp;gt;M_{1}&amp;lt;/tex&amp;gt;, то оптимальность очевидна &amp;lt;tex&amp;gt;(C_{max} \geqslant \sum\limits_{i \in G_{1}} p_{i1})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Иначе &amp;lt;tex&amp;gt;C_{max}&amp;lt;/tex&amp;gt; достигается на &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда либо &amp;lt;tex&amp;gt;M_{2}&amp;lt;/tex&amp;gt; работает без прерываний и оптимальность очевидна.&lt;br /&gt;
Или есть прерывания.&lt;br /&gt;
Тогда целевая функция равна ответу задачи [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]] для работ &amp;lt;tex&amp;gt;I_{21}&amp;lt;/tex&amp;gt;, который оптимален.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
==Сложность алгоритма==&lt;br /&gt;
Время работы алгоритма равно времени работы алгоритма  [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]], то есть &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Peter Brucker. «Scheduling Algorithms» {{---}} «Springer», 2006 г. 179 {{---}} 180 стр. {{---}} ISBN 978-3-540-69515-8&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>Zemskovk</name></author>	</entry>

	</feed>