O2Cmax — различия между версиями
Dimitrova (обсуждение | вклад) (→Псевдокод) |
м (rollbackEdits.php mass rollback) |
||
(не показано 27 промежуточных версий 6 участников) | |||
Строка 1: | Строка 1: | ||
− | == | + | <tex dpi = 200>O2 \mid \mid C_{max}</tex> |
− | Рассмотрим задачу: | + | {{Задача |
− | + | |definition=Рассмотрим задачу: | |
− | + | *дано <tex>n</tex> работ и <tex>2</tex> станка, | |
− | + | *для каждой работы известно её время выполнения на каждом станке. | |
− | + | Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках.}} | |
− | Требуется минимизировать время окончания всех работ, если каждую работу необходимо выполнить на обоих станках. | ||
== Описание алгоритма == | == Описание алгоритма == | ||
Пусть <tex>a_{i}</tex> {{---}} время выполнения <tex>i</tex>-ой работы на первом станке, а <tex>b_{i}</tex> {{---}} на втором.<br/> | Пусть <tex>a_{i}</tex> {{---}} время выполнения <tex>i</tex>-ой работы на первом станке, а <tex>b_{i}</tex> {{---}} на втором.<br/> | ||
− | + | #Разобьём все работы на два множества: <tex>I = \{i \mid a_{i} \leqslant b_{i}; i = 1, \dots, n\}</tex> и <tex>J = \{i \mid a_{i} > b_{i}; i = 1, \dots, n\}</tex>. | |
− | + | #Найдем такие <tex> x </tex> и <tex> y </tex>, что <tex>a_{x} = \max \limits_{i \in I} \{a_{i}\}</tex> и <tex>b_{y} = \max \limits_{i \in J} \{b_{i}\}</tex>. | |
− | < | + | #Построим оптимальное значение целевой функции: <tex>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}\}\}</tex>. |
− | + | # Рассмотрим два случая: | |
− | + | ## <tex>a_{x} > b_{y}</tex>. Будем строить расписание с двух концов: | |
− | + | ##*Строим расписание слева: выполняем на первом станке все работы из <tex>I \setminus \{x\}</tex>, а на втором выполняем первой работу <tex>x</tex>, затем <tex>I \setminus \{x\}</tex> в том же порядке, что и на первом станке. | |
− | + | ##*Теперь, упираясь в правую границу, равную <tex> C_{max} </tex>, можно построить расписание справа: выполняем на первом станке все работы из <tex>J</tex>, затем <tex>x</tex>, а для второго выполняем работы из <tex>J</tex>.[[Файл:Picture2.gif|500px|center]] | |
− | + | ## <tex>a_{x} \leqslant b_{y}</tex>. Сводится к первому, если поменять местами станки и соответствующие списки времён выполнения, при этом надо заново выполнить пункты 1,2 и 3. При выдаче ответа меняем станки обратно местами. | |
− | |||
− | |||
− | |||
− | |||
− | [[Файл: | ||
==Доказательство корректности алгоритма== | ==Доказательство корректности алгоритма== | ||
Строка 28: | Строка 22: | ||
Расписание, построенное данным алгоритмом, является корректным и оптимальным. | Расписание, построенное данным алгоритмом, является корректным и оптимальным. | ||
|proof= | |proof= | ||
− | Чтобы доказать корректность, надо доказать, что на каждом станке | + | Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.<br/> |
− | Первое утверждение вытекает из того, что мы строили расписание, опираясь на <tex>C_{max}</tex>. Из построения <tex>C_{max} \ | + | Первое утверждение вытекает из того, что мы строили расписание, опираясь на <tex>C_{max}</tex>. Из построения <tex>C_{max} \geqslant \sum \limits_{i = 1}^{n}a_{i}, \sum \limits_{i = 1}^{n}b_{i}</tex>, следовательно на каждом станке в любой момент времени выполняется не более одной работы.<br/> |
− | Докажем теперь второе утверждение. У нас имеется | + | Докажем теперь второе утверждение. У нас имеется три блока работ: <tex> I \setminus \{x\}, \{x\}, J</tex>. |
− | + | # Для блока <tex> \{x\}</tex> это следует из того, что <tex> C_{max} \geqslant a_{x}+b_{x}</tex>, а работа <tex> x </tex> выполняется с разных концов станков. Получили, что отрезки выполнения работы <tex> x </tex> на разных станках не пересекаются. | |
− | + | # Покажем, что любая работа из <tex> I \setminus \{x\}</tex> начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:<br><tex>\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}</tex>, где <tex>1 \dots k</tex> {{---}} это работы, выполняемые на первом станке во время данного блока.<br>Это неравенство следует из выбора <tex>I</tex> и из того, что <tex>b_{x} \geqslant a_{x} \geqslant a_{i}, \forall i \in I</tex>.<br>Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.<br> | |
− | + | # Покажем, что любая работа из <tex>J</tex> начинает выполняться на втором станке позже, чем заканчивает выполняться на первом. Для этого рассмотрим сумму:<br><tex>\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}</tex>, где <tex>1 \dots k</tex> {{---}} это работы, выполняемые на втором станке во время данного блока. | |
− | < | + | Это неравенство следует из выбора <tex>J</tex> и из того, что <tex>a_{x} \geqslant a_{i}, \forall i \in I</tex>. |
− | Это неравенство следует из выбора <tex>I</tex> и из того, что <tex>b_{x} \ | + | Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом. |
− | Получили, что | + | |
− | |||
− | < | ||
− | Это неравенство следует из выбора <tex>J</tex> и из того, что <tex>a_{x} \ | ||
− | Получили, что | ||
− | |||
Итого мы доказали корректность.<br/> | Итого мы доказали корректность.<br/> | ||
− | Оптимальность вытекает | + | Оптимальность вытекает из того, что <tex>C_{max}</tex> не может быть меньше <tex>\sum \limits_{i = 1}^{n} a_i,\ \sum \limits_{i = 1}^{n} b_i, \ \max \limits_{i = 1}^{n}\{a_i + b_{i}\}</tex>, а из построения оно равно максимуму из этих значений. |
}} | }} | ||
==Псевдокод== | ==Псевдокод== | ||
− | + | <font color=green>//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.<br>//Функция возвращает пару из расписания для первого станка и расписания для второго станка.</font> | |
− | + | '''function''' scheduling(a: '''int'''[n], b: '''int[n]'''): '''pair<int[n], int[n]>''' | |
− | + | <tex>I = \varnothing </tex> | |
− | + | <tex>J = \varnothing </tex> | |
− | + | <tex>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}\}\}</tex> | |
− | + | '''for''' <tex>i = 1</tex> '''to''' <tex>n</tex> | |
− | + | '''if''' <tex>a_{i} \leqslant b_{i}</tex> | |
− | + | <tex> I = I \cup \{i\} </tex> | |
− | + | '''else''' | |
− | + | <tex> J = J \cup \{i\} </tex> | |
− | + | Найти <tex>x</tex>, где <tex>a_{x} = \max \limits_{i \in I} \{a_{i}\}</tex> | |
− | + | Найти <tex>y</tex>, где <tex>b_{y} = \max \limits_{i \in J} \{b_{i}\}</tex> | |
− | + | '''if''' <tex>a_{x} > b_{y}</tex> | |
− | + | Начиная с <tex>0</tex> на первом станке расставляем расписание для <tex>I \setminus \{x\}</tex> | |
− | + | Начиная с <tex>0</tex> на втором станке расставляем расписание для <tex>\{x\}</tex>, затем для <tex>I \setminus \{x\}</tex><br/> | |
− | + | От правой границы {{---}} <tex>C_{max}</tex> на первом станке расставляем расписание для <tex>\{x\}</tex>, затем для <tex>J</tex> | |
− | + | От правой границы {{---}} <tex>C_{max}</tex> на втором станке расставляем расписание для <tex>J</tex><br/> | |
− | + | '''pair<int[n], int[n]>''' ans = пара из расписания для первого станка и расписания для второго станка | |
− | + | '''return''' ans | |
− | + | '''else''' | |
− | + | '''pair<int[n], int[n]>''' ans = scheduling(b, a) | |
− | + | Меняем местами расписания для станков в ans | |
− | + | '''return''' ans | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==Сложность алгоритма== | ==Сложность алгоритма== | ||
Каждое из множеств в сумме содержит <tex>n</tex> элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется <tex>O(n)</tex> операций, чтобы составить расписание для каждой работы из множества нам потребуется так же <tex>O(n)</tex> операций. Получаем сложность алгоритма <tex>O(n)</tex>. | Каждое из множеств в сумме содержит <tex>n</tex> элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется <tex>O(n)</tex> операций, чтобы составить расписание для каждой работы из множества нам потребуется так же <tex>O(n)</tex> операций. Получаем сложность алгоритма <tex>O(n)</tex>. | ||
+ | |||
+ | ==См. также== | ||
+ | * [[P2precpi1Lmax|<tex>P2 \mid prec, p_i = 1 \mid L_{\max}</tex>]] | ||
+ | * [[R2Cmax|<tex>R2 \mid \mid C_{max}</tex>]] | ||
+ | * [[F2Cmax|<tex>F2 \mid \mid C_{max}</tex>]] | ||
+ | * [[O2Cmax|<tex>O2 \mid \mid C_{max}</tex>]] | ||
+ | * [[J2ni2Cmax|<tex>J2 \mid n_{i} \leqslant 2 \mid C_{max}</tex>]] | ||
+ | * [[J2pij1Lmax| <tex>J2\mid p_{ij} = 1\mid L_{max}</tex>]] | ||
+ | |||
+ | == Источники информации == | ||
+ | * Peter Brucker «Scheduling Algorithms», fifth edition, Springer {{---}} с. 158{{---}}160 ISBN 978-3-540-69515-8 | ||
+ | |||
+ | [[Категория: Алгоритмы и структуры данных]] | ||
+ | [[Категория: Теория расписаний]] |
Текущая версия на 19:13, 4 сентября 2022
Задача: |
Рассмотрим задачу:
|
Содержание
Описание алгоритма
Пусть
- Разобьём все работы на два множества: и .
- Найдем такие и , что и .
- Построим оптимальное значение целевой функции: .
- Рассмотрим два случая:
-
- Строим расписание слева: выполняем на первом станке все работы из , а на втором выполняем первой работу , затем в том же порядке, что и на первом станке.
- Теперь, упираясь в правую границу, равную , можно построить расписание справа: выполняем на первом станке все работы из , затем , а для второго выполняем работы из .
. Будем строить расписание с двух концов:
- . Сводится к первому, если поменять местами станки и соответствующие списки времён выполнения, при этом надо заново выполнить пункты 1,2 и 3. При выдаче ответа меняем станки обратно местами.
-
Доказательство корректности алгоритма
Теорема: |
Расписание, построенное данным алгоритмом, является корректным и оптимальным. |
Доказательство: |
Чтобы доказать корректность, надо доказать, что на каждом станке в любой момент времени выполняется не более одной работы, и что каждая работа в каждый момент времени выполняется не более, чем на одном станке.
Это неравенство следует из выбора и из того, что . Получили, что каждая работа из этого блока начинает выполняться на втором станке позже, чем она заканчивается на первом.Итого мы доказали корректность. |
Псевдокод
//Функция принимает список из времён выполнения на первом станке a и времён выполнения на втором станке b.
//Функция возвращает пару из расписания для первого станка и расписания для второго станка. function scheduling(a: int[n], b: int[n]): pair<int[n], int[n]> for to if else Найти , где Найти , где if Начиная с на первом станке расставляем расписание для Начиная с на втором станке расставляем расписание для , затем для
От правой границы — на первом станке расставляем расписание для , затем для От правой границы — на втором станке расставляем расписание для
pair<int[n], int[n]> ans = пара из расписания для первого станка и расписания для второго станка return ans else pair<int[n], int[n]> ans = scheduling(b, a) Меняем местами расписания для станков в ans return ans
Сложность алгоритма
Каждое из множеств в сумме содержит
элементов. Следовательно, чтобы найти максимум в каждом из множеств нам потребуется операций, чтобы составить расписание для каждой работы из множества нам потребуется так же операций. Получаем сложность алгоритма .См. также
Источники информации
- Peter Brucker «Scheduling Algorithms», fifth edition, Springer — с. 158—160 ISBN 978-3-540-69515-8