Ppi1riintegerLmax — различия между версиями
Eadm (обсуждение | вклад) |
Shersh (обсуждение | вклад) м (→Псевдокод) |
||
Строка 11: | Строка 11: | ||
Алгоритм принимает на вход массив пар, где первый элемент является временем появления <tex>r_i</tex> работы, а второй её дедлайном <tex>d_i</tex>, и возвращает расписание, представленное массивом, где на позиции <tex>i</tex> стоит момент обработки работы <tex>i</tex>. | Алгоритм принимает на вход массив пар, где первый элемент является временем появления <tex>r_i</tex> работы, а второй её дедлайном <tex>d_i</tex>, и возвращает расписание, представленное массивом, где на позиции <tex>i</tex> стоит момент обработки работы <tex>i</tex>. | ||
− | '''function''' scheduling(jobs: '''<int, int>''' | + | '''function''' scheduling(jobs: '''<int, int>[n]''') -> '''int[n]''' |
sort(jobs) <font color=green>// сортируем работы в порядке неубывания времени появления</font> | sort(jobs) <font color=green>// сортируем работы в порядке неубывания времени появления</font> | ||
'''int''' j = 1 <font color=green>// последняя невыполненная работа</font> | '''int''' j = 1 <font color=green>// последняя невыполненная работа</font> | ||
Строка 37: | Строка 37: | ||
[[Файл:Ppi1riintegerLmax bad.png|320px|thumb|right|Пример работы алгоритма при вещественных <tex>r_i</tex>]] | [[Файл:Ppi1riintegerLmax bad.png|320px|thumb|right|Пример работы алгоритма при вещественных <tex>r_i</tex>]] | ||
Внутренний цикл <tex>\mathrm{while}</tex> распределяет работы блоками, в которых они выполняются без простоя станков. После окончания такого блока, время начала выполнения следующего будет равно текущему значению <tex>r_j</tex>. | Внутренний цикл <tex>\mathrm{while}</tex> распределяет работы блоками, в которых они выполняются без простоя станков. После окончания такого блока, время начала выполнения следующего будет равно текущему значению <tex>r_j</tex>. | ||
+ | |||
=== Асимптотика === | === Асимптотика === | ||
Сначала мы сортируем работы, что занимает <tex> \mathcal{O}(n\log{n})</tex>. Далее идёт цикл, в котором мы <tex>n</tex> раз кладём элемент в кучу и <tex>n</tex> раз извлекаем, что также занимает <tex> \mathcal{O}(n\log{n})</tex> времени. В итоге всё вместе составляет асимптотику алгоритма <tex> \mathcal{O}(n\log{n})</tex>. | Сначала мы сортируем работы, что занимает <tex> \mathcal{O}(n\log{n})</tex>. Далее идёт цикл, в котором мы <tex>n</tex> раз кладём элемент в кучу и <tex>n</tex> раз извлекаем, что также занимает <tex> \mathcal{O}(n\log{n})</tex> времени. В итоге всё вместе составляет асимптотику алгоритма <tex> \mathcal{O}(n\log{n})</tex>. |
Версия 23:31, 4 июня 2016
Задача: |
Дано | однородных станков, работающих параллельно, и работ с временем выполнения , временем появления , заданным целым числом, и моментом времени , к которому нужно выполнить работу. Необходимо построить такое расписание, чтобы значение максимального опоздания было минимальным.
Содержание
Описание алгоритма
Идея
Отсортируем все работы по времени появления в неубывающем порядке так, что
. Теперь будем выполнять доступные на данный момент работы в порядке неубывания дедлайнов . То есть, если в момент времени есть свободные станки и есть невыполненные работы такие, что , то назначаем работу с наименьшим дедлайном на свободный станок.Псевдокод
Алгоритм принимает на вход массив пар, где первый элемент является временем появления
работы, а второй её дедлайном , и возвращает расписание, представленное массивом, где на позиции стоит момент обработки работы .function scheduling(jobs: <int, int>[n]) -> int[n] sort(jobs) // сортируем работы в порядке неубывания времени появления int j = 1 // последняя невыполненная работа int[n] ans // массив, куда будет записано расписание Heap<int> M // куча, в которой будем хранить доступные на данный момент работы в порядке неубывания дедлайнов while j <= n int time = jobs[j].first // время начала выполнения текущего блока работ while jobs[j].first <= time // добавляем в кучу все невыполненные работы, доступные на данный момент M.push(j) j++ int k = 0 // количество занятых станков в данный момент времени while M.notEmpty i = M.pop() // получаем доступную работу с наименьшим дедлайном ans[i] = t // назначаем работу i на время t if k + 1 < m // если в момент t есть свободный станок, то назначаем работу i на него k++ else // иначе увеличиваем время и обновляем список доступных работ t++ k = 0 while jobs[j].first <= time M.push(j) j++
Внутренний цикл
распределяет работы блоками, в которых они выполняются без простоя станков. После окончания такого блока, время начала выполнения следующего будет равно текущему значению .Асимптотика
Сначала мы сортируем работы, что занимает
. Далее идёт цикл, в котором мы раз кладём элемент в кучу и раз извлекаем, что также занимает времени. В итоге всё вместе составляет асимптотику алгоритма .Замечание
Стоит отметить тот факт, что если снять ограничение на целочисленность
и позволить им принимать вещественные значения, то представленный алгоритм перестанет строить оптимальное расписание, как видно из контрпримера.Доказательство корректности алгоритма
Теорема: |
Приведенный алгоритм строит оптимальное расписание для задачи . |
Доказательство: |
Пусть — расписание построенное предложенным алгоритмом, а оптимальное расписание со следующими свойствами:
|
См. также
Источники информации
- Peter Brucker «Scheduling Algorithms», fifth edition, Springer — с. 111-112 ISBN 978-3-540-69515-8