1ridipi1
| Задача: |
| Дан один станок на котором нужно выполнить работ. Для каждой работы известны моменты времени, когда можно начинать её выполнять — и когда необходимо закончить её выполнение — . Время выполнения у всех работ одинаково и равно 1. Необходимо узнать, можно ли построить расписание, при котором все работы будут выполнены. |
Содержание
Алгоритм
Упрощенная версия
Для начала решим более простую версию исходной задачи, когда все .
Описание алгоритма
Будем выполнять работы в порядке возрастания их дедлайна . Утверждается, что это оптимальное расписание. Приведем реализацию, на основе которой мы вскоре построим решение основной задачи:
Псевдокод
Пусть — множество еще не включенных в расписание задач. Изначально в нем находятся все задачи.
function solve(d: int[n]): boolean
int
for to
if
// расписание составить невозможно
return false
else
// выполняем работу номер k
return true
Сложность алгоритма , если в качестве использовать структуру, которая позволяет поиск элемента с минимальным и его удаление за , например двоичная куча.
Доказательство корректности и оптимальности
| Теорема: |
Приведенный алгоритм строит оптимальное расписание для задачи . |
| Доказательство: |
| Докажем от противного. Пусть в оптимальном расписании, где все работы укладываются в дедлайны, сначала идет работа , а потом , причем . Посмотрим, что произойдет, если в расписании поменять их местами. Так как они обе выполняются за единицу времени, для всех задач, кроме -й и -й время их завершения не поменялось. Для -й же работы стало меньше, что только лучше. увеличилось и стало равно старому однако, раз -я работа раньше укладывалась в дедлайн, то , а значит и -я работа все еще укладывается в свой дедлайн, и наша замена ничего не испортила. |
Исходная задача
Теперь перейдем к решению основной задачи.
Описание алгоритма
Теперь не все задачи доступны изначально. Однако утверждается, что очередную задачу теперь достаточно выбирать с минимальным из всех, которые уже доступны. Если эта работа уже просрочена, значит хорошее расписание построить нельзя.
Псевдокод
Пусть — множество ещё не включенных в расписание работ, к выполнению которых уже можно приступить. Изначально пустое. Отсортируем работы по порядку их появления.
function solve(r: int[n], d: int[n]): boolean
int
int
for to
if
while
|
if
// расписание составить невозможно
return false
else
// выполняем работу номер k
return true
Сложность алгоритма , если в качестве использовать структуру, которая позволяет поиск элемента с минимальным и его удаление за , например двоичная куча.
Доказательство корректности и оптимальности
| Теорема: |
Приведенный алгоритм строит оптимальное расписание для задачи . |
| Доказательство: |
|
Пусть с помощью нашего алгоритма составить хорошее расписание не удалось. Докажем, что в этом случае хорошего расписания не существует. Заметим, что расписание состоит из непрерывных блоков, между которыми есть пропуски — все поступившие работы выполнены, а новых работ ещё не появилось. Расписание может состоять из одного блока. Рассмотрим первый блок, для которого не получилось составить расписание. Возьмем в нём первую работу, для которой не нашлось места. Пусть её индекс будет равен . Попробуем вставить эту работу в расписание. До блока её вставить нельзя, так как больше или равно времени начала блока. А в блоке нет пропусков, поэтому нужно поменять её с какой-то -й, которая уже стоит в этом блоке расписания. У всех таких работ , так как в алгоритме мы каждый раз брали работу с минимальным . Но -ю работу нельзя выполнить после -й. Значит -ю работу выполнить нельзя. |
См. также
Источники информации
- P. Brucker. «Scheduling Algorithms» (2006), 5th edition.