1ridipi1 — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (Подкорректировано доказательство)
(Добавлено 1 | d_i,p_i=1 | -, небольшие изменения в тексте)
Строка 3: Строка 3:
  
 
==Алгоритм==
 
==Алгоритм==
Идея алгоритма в том, чтобы из тех работ, которые уже можно выполнить, ставить в расписание ту, у которой наименьшее <tex>d_{i}</tex>. Если эта работа уже просрочена, значит хорошее расписание построить нельзя.
+
 
 +
===1 | d_i, p_i=1 | -===
 +
 
 +
Для начала решим задачу, если все <tex>r_{i}=1</tex>, то есть <tex>1 | d_{i}, p_{i}=1 | -</tex>.
 +
 
 +
Будем выполнять работы в порядке возрастания их дедлайна <tex>d_{i}</tex>. Утверждается, что это оптимальное расписание.
 +
Приведем реализацию, на основе которой мы вскоре построим решение основной задачи:
 +
 
 +
Пусть <tex>S</tex> — множество еще не включенных в расписание задач. Изначально в нем находятся все задачи.
 +
  <tex>S = \{1, 2, \ldots, n\}</tex>
 +
  <tex>time = 1;</tex>
 +
  '''for''' <tex> i = 1 </tex> '''to''' <tex> n </tex>:
 +
      <tex>d_{k} = min\{d_{i}</tex> | <tex>i \in S\}</tex>
 +
      '''if''' <tex>d_{k} \le time</tex>:
 +
          Расписание составить невозможно
 +
      '''else''':
 +
          //выполняем работу номер <tex>k</tex>
 +
          <tex>S \leftarrow S \setminus \{k\}</tex>
 +
          <tex>time = time + 1;</tex>
 +
 
 +
Сложность алгоритма <tex>O(n\log n)</tex>, если в качестве <tex>S</tex> использовать структуру, которая позволяет поиск элемента с минимальным <tex>d_{i}</tex> за <tex>O(\log n)</tex>.
 +
 
 +
'''Доказательство корректности алгоритма'''
 +
 
 +
Докажем от противного. Пусть в оптимальном расписании, где все работы укладываются в дедлайны, сначала идет работа <tex>i</tex>, а потом <tex>j</tex>, причем <tex>d_{i} > d_{j}</tex>. Посмотрим, что произойдет, если в расписании поменять их местами. Так как они обе выполняются за единицу времени, для всех задач, кроме <tex>i</tex>-й и <tex>j</tex>-й время их завершения <tex>C_{i}</tex> не поменялось. Для <tex>j</tex>-й же работы <tex>C_{j}</tex> стало меньше, что только лучше. <tex>C_{i}</tex> увеличилось и стало равно старому <tex>C_{j}</tex> однако, раз <tex>j</tex>-я работа раньше укладывалась в дедлайн, то <tex>C_{i} = C_{j}^{old} \le d_{j} < d_{i}</tex>, а значит и <tex>i</tex>-я работа все еще укладывается в свой дедлайн, и наша замена ничего не испортила.
 +
 
 +
===1 | r_i, d_i, p_i=1 | -===
 +
 
 +
Теперь перейдем к основной задаче — <tex>1 | r_{i}, d_{i}, p_{i}=1 | -</tex>.
 +
Теперь не все задачи доступны изначально. Однако утверждается, что очередную задачу теперь достаточно выбирать с минимальным <tex>d_{i}</tex> из всех, которые уже доступны. Если эта работа уже просрочена, значит хорошее расписание построить нельзя.
  
 
Пусть <tex>S</tex> — множество ещё не включенных в расписание работ, к выполнению которых уже можно приступить. Изначально <tex>S</tex> пустое.
 
Пусть <tex>S</tex> — множество ещё не включенных в расписание работ, к выполнению которых уже можно приступить. Изначально <tex>S</tex> пустое.
Строка 22: Строка 51:
 
           Расписание составить невозможно
 
           Расписание составить невозможно
 
       '''else''':
 
       '''else''':
 +
          //выполняем работу номер <tex>k</tex>
 
           <tex>S \leftarrow S \setminus \{k\}</tex>
 
           <tex>S \leftarrow S \setminus \{k\}</tex>
 
           <tex>time = time + 1;</tex>
 
           <tex>time = time + 1;</tex>

Версия 21:43, 4 июня 2016

Постановка задачи

Дан один станок на котором нужно выполнить [math]n[/math] работ. Для каждой работы известны моменты времени, когда можно начинать её выполнять — [math]r_{i}[/math] и когда необходимо закончить её выполнение — [math]d_{i}[/math]. Время выполнения [math]p_{i}[/math] у всех работ одинаково и равно 1. Необходимо узнать, можно ли построить расписание, при котором все работы будут выполнены.

Алгоритм

1 | d_i, p_i=1 | -

Для начала решим задачу, если все [math]r_{i}=1[/math], то есть [math]1 | d_{i}, p_{i}=1 | -[/math].

Будем выполнять работы в порядке возрастания их дедлайна [math]d_{i}[/math]. Утверждается, что это оптимальное расписание. Приведем реализацию, на основе которой мы вскоре построим решение основной задачи:

Пусть [math]S[/math] — множество еще не включенных в расписание задач. Изначально в нем находятся все задачи.

 [math]S = \{1, 2, \ldots, n\}[/math]
 [math]time = 1;[/math]
 for [math] i = 1 [/math] to [math] n [/math]:
     [math]d_{k} = min\{d_{i}[/math] | [math]i \in S\}[/math]
     if [math]d_{k} \le time[/math]:
         Расписание составить невозможно
     else:
         //выполняем работу номер [math]k[/math]
         [math]S \leftarrow S \setminus \{k\}[/math]
         [math]time = time + 1;[/math]

Сложность алгоритма [math]O(n\log n)[/math], если в качестве [math]S[/math] использовать структуру, которая позволяет поиск элемента с минимальным [math]d_{i}[/math] за [math]O(\log n)[/math].

Доказательство корректности алгоритма

Докажем от противного. Пусть в оптимальном расписании, где все работы укладываются в дедлайны, сначала идет работа [math]i[/math], а потом [math]j[/math], причем [math]d_{i} \gt d_{j}[/math]. Посмотрим, что произойдет, если в расписании поменять их местами. Так как они обе выполняются за единицу времени, для всех задач, кроме [math]i[/math]-й и [math]j[/math]-й время их завершения [math]C_{i}[/math] не поменялось. Для [math]j[/math]-й же работы [math]C_{j}[/math] стало меньше, что только лучше. [math]C_{i}[/math] увеличилось и стало равно старому [math]C_{j}[/math] однако, раз [math]j[/math]-я работа раньше укладывалась в дедлайн, то [math]C_{i} = C_{j}^{old} \le d_{j} \lt d_{i}[/math], а значит и [math]i[/math]-я работа все еще укладывается в свой дедлайн, и наша замена ничего не испортила.

1 | r_i, d_i, p_i=1 | -

Теперь перейдем к основной задаче — [math]1 | r_{i}, d_{i}, p_{i}=1 | -[/math]. Теперь не все задачи доступны изначально. Однако утверждается, что очередную задачу теперь достаточно выбирать с минимальным [math]d_{i}[/math] из всех, которые уже доступны. Если эта работа уже просрочена, значит хорошее расписание построить нельзя.

Пусть [math]S[/math] — множество ещё не включенных в расписание работ, к выполнению которых уже можно приступить. Изначально [math]S[/math] пустое. Отсортируем работы по порядку их появления.

Алгоритм [math]1 | r_{i}, d_{i}, p_{i}=1 | -[/math]:

 [math]S = \varnothing;[/math]
 [math]j = 1;[/math]
 [math]time = 1;[/math]
 for [math] i = 1 [/math] to [math] n [/math]:
     if [math]S == \varnothing[/math]:
         [math]time=r_{j}[/math]
     while [math]time==r_{j}[/math]:
         [math]S \leftarrow S \cup \{j\}[/math]
         [math]j = j + 1;[/math]
     [math]d_{k} = min\{d_{i}[/math] | [math]i \in S\}[/math]
     if [math]d_{k} \le time[/math]:
         Расписание составить невозможно
     else:
         //выполняем работу номер [math]k[/math]
         [math]S \leftarrow S \setminus \{k\}[/math]
         [math]time = time + 1;[/math]

Сложность алгоритма [math]O(n\log n)[/math], если в качестве [math]S[/math] использовать структуру, которая позволяет поиск элемента с минимальным [math]d_{i}[/math] за [math]O(\log n)[/math].

Доказательство корректности алгоритма

Пусть с помощью нашего алгоритма составить хорошее расписание не удалось. Докажем, что в этом случае хорошего расписания не существует. Заметим, что расписание состоит из непрерывных блоков, между которыми есть пропуски — все поступившие работы выполнены, а новых работ ещё не появилось. Расписание может состоять из одного блока.

Рассмотрим первый блок, для которого не получилось составить расписание. Возьмем в нём первую работу, для которой не нашлось места. Пусть её индекс будет равен [math]k[/math]. Попробуем вставить эту работу в расписание. До блока её вставить нельзя, так как [math]r_{i}[/math] больше или равно времени начала блока. А в блоке нет пропусков, поэтому нужно поменять её с какой-то [math]i[/math]-й, которая уже стоит в этом блоке расписания. У всех таких работ [math]d_{i} \le d_{k}[/math], так как в алгоритме мы каждый раз брали работу с минимальным [math]d_{i}[/math]. Но [math]i[/math]-ю работу нельзя выполнить после [math]k[/math]-й. Значит [math]k[/math]-ю работу выполнить нельзя.

Источники информации

  • P. Brucker. Scheduling Algorithms (2006), 5th edition, стр. 200