J2pij1Lmax — различия между версиями
| System29a (обсуждение | вклад) | System29a (обсуждение | вклад)  | ||
| Строка 1: | Строка 1: | ||
| {{в разработке}} | {{в разработке}} | ||
| − | + | ===Условие задачи=== | |
| − | Допустим, самым ранним моментом, когда операция может начать выполняться, будет момент времени 0, а верхняя граница момента начала выполнения последней операции обозначим за <tex>t_{max}</tex>. К примеру, мы можем выбрать <tex>t_{max} = r</tex>. Тогда расписание можно представить как два массива <tex>A(t)</tex> и <tex>B(t) (t = 0, | + | ===Описание решения=== | 
| + | Дано <tex>n</tex> работ <tex>i = 1,\ldots,n</tex> и две машины, обозначенные как A и B. <tex>i</tex>-тая работа состоит из <tex>n_i</tex> операций <tex>O_{ij} (j = 1,\ldots n_i)</tex>, которые должны быть выполнены последовательно и, при этом, если <tex>O_{ij} </tex>операция была совершена на машине <tex>A (B)</tex>, то операция <tex>O_{i,j-1}</tex> должна быть совершена на машине <tex>B (A)</tex>. Таким образом, <tex>i</tex>-тая работа может характеризоваться двумя значениями: количество операций <tex>n_i</tex> и машина, на которой была совершена первая операция. Пусть <tex>r = \sum_{i=1}^n N_i</tex> {{---}} общее количество операций. | ||
| + | |||
| + | Допустим, самым ранним моментом, когда операция может начать выполняться, будет момент времени 0, а верхняя граница момента начала выполнения последней операции обозначим за <tex>t_{max}</tex>. К примеру, мы можем выбрать <tex>t_{max} = r</tex>. Тогда расписание можно представить как два массива <tex>A(t)</tex> и <tex>B(t) (t = 0,\ldots,t_{max})</tex>, где <tex>A(t) = O_{ij}</tex>, если операция <tex>O_ij</tex> должна выполниться на машине <tex>A</tex> в момент времени <tex>t</tex> и <tex>A(t) =</tex><tex> \emptyset</tex>, если машина <tex>A</tex> простаивает в этот момент. Будем называть <tex>\emptyset</tex> пустой операцией. И для каждой операции <tex>O_{ij}</tex>, выполняющейся на машине <tex>A</tex> существует <tex>t</tex>, для которого <tex>A(t) = O_{ij}</tex>. Аналогично для <tex>B_i</tex>. Расписание достижимо тогда и только тогда, когда из <tex>A(t) (B(t)) = O_{ij} , 1 < j \le n_i</tex> следует <tex>O_{i,j-1} = B(s) (A(s))</tex> для некоторого <tex>s < t</tex>, и первая операция для каждой работы запланирована на нужной машине. Перестановку всех операций будем называть списком. Для данный списка <tex>L</tex> осуществимое расписание может быть создано следующим способом: планируем выполнять операции в порядке, соответствующим <tex>L</tex>, причем каждую операцию стараемся выполнить как можно раньше. Подобное расписание будем называть соответствующим <tex>L</tex> расписанием.    | ||
| <tex>С_i</tex> {{---}} время окончания работы <tex>i</tex> в достижимом расписании <tex>y = (A(t), B(t))</tex> можно рассчитать как: | <tex>С_i</tex> {{---}} время окончания работы <tex>i</tex> в достижимом расписании <tex>y = (A(t), B(t))</tex> можно рассчитать как: | ||
| Строка 9: | Строка 12: | ||
| Задача заключается в том, что для данного каждой работе <tex>i</tex> дедлайна <tex>d_i \ge 0</tex> мы хотим найти достижимое расписание с наименьшими максимальным временем опоздания: | Задача заключается в том, что для данного каждой работе <tex>i</tex> дедлайна <tex>d_i \ge 0</tex> мы хотим найти достижимое расписание с наименьшими максимальным временем опоздания: | ||
| − | <tex>max{C_i - d_i | i = 1,  | + | <tex>max\{C_i - d_i | i = 1, \ldots, n\}</tex>   | 
| Следующий алгоритм решает эту задачу: | Следующий алгоритм решает эту задачу: | ||
| − | + | * Введём для каждой операции <tex>O_{ij}</tex> величину <tex>l(O_{ij}) = d_i - n_i + j</tex> | |
| − | + | * Создадим список всех операций <tex>L</tex>, упорядоченный в порядке неубывания значений <tex>l(O_{ij})</tex>   | |
| − | + | * Найдем соответствующее списку <tex>L</tex> расписание. | |
| Этот алгоритм может быть реализованным с асимптотикой <tex>O(r \log r)</tex>. | Этот алгоритм может быть реализованным с асимптотикой <tex>O(r \log r)</tex>. | ||
| Однако, мы будем использовать эвристику с хешами и улучшим асимптотику алгоритма до <tex>O(r)</tex>. | Однако, мы будем использовать эвристику с хешами и улучшим асимптотику алгоритма до <tex>O(r)</tex>. | ||
| − | Мы предполагаем, что <tex>d_i \ge 0</tex> для <tex>i = 1, | + | Мы предполагаем, что <tex>d_i \ge 0</tex> для <tex>i = 1,\ldots,n</tex> и хотя бы для одной работы <tex>i</tex> <tex>d_i = 0</tex>. Иначе, вычтем из всех <tex>d_i</tex> минимальное значение по <tex>d_i</tex> | 
| − | Так как <tex>C_i \ge 1</tex> для всех <tex>i = 1, | + | Так как <tex>C_i \ge 1</tex> для всех <tex>i = 1,\ldots,n</tex> и <tex>d_i = 0</tex> справедливо <tex>L_i = C_i - d_i \ge 1</tex> как минимум для одной работы <tex>i</tex>. К тому же, можно предположить, что <tex>C_i \le r</tex>. Таким образом, работы с <tex>d_i > r - 1</tex>, то есть c <tex>L_i = C_i - d_i < 1</tex> можно смело игнорировать. Они не влияют на значение улучшаемой функции <tex>max(L_i)</tex>, так как для некого <tex>i L_i \ge 1</tex> Можно выполнять эти работы в любом порядке после всех остальных. Для оставшихся операций <tex>O_{ij}</tex> мы имеем: | 
| <tex>-r + 1 \le l(O_{ij}) = d_i - n_i + j \le r - 1</tex> | <tex>-r + 1 \le l(O_{ij}) = d_i - n_i + j \le r - 1</tex> | ||
| Строка 28: | Строка 31: | ||
| Каждую операцию мы кладём в соответствующую корзину <tex>L(k)</tex>, где <tex>k = l(O_{ij}) = d_i - n_i + j(-r + 1 \le k \le r - 1)</tex>. На втором шаге мы планируем операции соответственно возрастающему по номеру корзины <tex>k</tex> порядку, где операции из одной корзины могут выполнятся в произвольном порядке. | Каждую операцию мы кладём в соответствующую корзину <tex>L(k)</tex>, где <tex>k = l(O_{ij}) = d_i - n_i + j(-r + 1 \le k \le r - 1)</tex>. На втором шаге мы планируем операции соответственно возрастающему по номеру корзины <tex>k</tex> порядку, где операции из одной корзины могут выполнятся в произвольном порядке. | ||
| − | Давайте детально рассмотрим алгоритм. <tex>T1</tex> и <tex>T2</tex> обозначают первый период времени <tex>t \ge 0</tex>, когда  | + | ===Алгоритм=== | 
| + | Давайте детально рассмотрим алгоритм. <tex>T1</tex> и <tex>T2</tex> обозначают первый период времени <tex>t \ge 0</tex>, когда соответствующие машины <tex>A</tex> и <tex>B</tex> бездействуют. <tex>LAST(i)</tex> обозначает время окончания последней запланированной операции <tex>i</tex>-той работы. <tex>Z</tex> {{---}} множество работ, где <tex>d_i \ge r</tex>   | ||
| − |   main() | + |   '''main()''' | 
|     '''for''' k: -r + 1 '''to''' r - 1 |     '''for''' k: -r + 1 '''to''' r - 1 | ||
|       <tex>L(k)</tex> = <tex>\emptyset</tex>; |       <tex>L(k)</tex> = <tex>\emptyset</tex>; | ||
| Строка 47: | Строка 51: | ||
|       '''while''' <tex>L(k) \ne \emptyset</tex> |       '''while''' <tex>L(k) \ne \emptyset</tex> | ||
|         Выбрать задание <tex>O_{ij}</tex> из <tex>L(k)</tex> |         Выбрать задание <tex>O_{ij}</tex> из <tex>L(k)</tex> | ||
| − |         <tex>L(k)</tex> = <tex>L(k)\ | + |         <tex>L(k)</tex> = <tex>L(k)\setminus\{O_{ij}\}</tex>; | 
|         schedule(<tex>O_{ij}</tex>)   |         schedule(<tex>O_{ij}</tex>)   | ||
|     '''while''' <tex>z \ne \emptyset</tex> |     '''while''' <tex>z \ne \emptyset</tex> | ||
|       Выбрать работу i из Z |       Выбрать работу i из Z | ||
| − |       Z = <tex>Z\ | + |       Z = <tex>Z \setminus\{i\}</tex>; | 
|       '''for''' j: 1 '''to''' <tex>n_i</tex> |       '''for''' j: 1 '''to''' <tex>n_i</tex> | ||
|         schedule(<tex>O_{ij}</tex>) 	 |         schedule(<tex>O_{ij}</tex>) 	 | ||
| − | + |   '''schedule(<tex>O_{ij}</tex>)''' | |
| − |   schedule(O_{ij}) | + |     '''if''' <tex>\mu_{ij}</tex> == A | 
| − |     if \mu_{ij} = A  | + |       '''if''' T1 < LAST(i)   | 
| − |       if T1 < LAST(i)  | + |         t = LAST(i) | 
| − |         t  | + |         A(t) = <tex>O_{ij}</tex> | 
| − |         A(t)  | + |       '''else''' | 
| − |       else | + |         t = T1; | 
| − |         t  | + |         A(t) = <tex>O_{ij}</tex>; | 
| − |         A(t)  | + |         '''while''' <tex>A(T_1)</tex> <tex>\ne \emptyset</tex> | 
| − |         while A(T_1) \ne \emptyset  | + |           T1 = T1 + 1; | 
| − |           T1  | + |     '''else''' | 
| − |     else | + |       '''if''' T2 < LAST(i) | 
| − |       if T2 < LAST(i)  | + |         t = LAST(i) | 
| − |         t  | + |         B(t) = <tex>O_{ij}</tex> | 
| − |         B(t)  | + |       '''else''' | 
| − |       else | + |         t = T2; | 
| − |         t  | + |         A(t) = <tex>O_{ij}</tex>; | 
| − |         A(t)  | + |         '''while''' <tex>B(T_2) \ne \emptyset</tex> | 
| − |         while B(T_2) \ne \emptyset  | + |           T2 = T2 + 1; | 
| − |           T2  | + |     LAST(i) = t + 1 | 
| − |     LAST(i)  | ||
| Очевидно, что количество шагов алгоритма ограничено <tex>O(r)</tex> | Очевидно, что количество шагов алгоритма ограничено <tex>O(r)</tex> | ||
Версия 21:39, 21 июня 2012
Условие задачи
Описание решения
Дано работ и две машины, обозначенные как A и B. -тая работа состоит из операций , которые должны быть выполнены последовательно и, при этом, если операция была совершена на машине , то операция должна быть совершена на машине . Таким образом, -тая работа может характеризоваться двумя значениями: количество операций и машина, на которой была совершена первая операция. Пусть — общее количество операций.
Допустим, самым ранним моментом, когда операция может начать выполняться, будет момент времени 0, а верхняя граница момента начала выполнения последней операции обозначим за . К примеру, мы можем выбрать . Тогда расписание можно представить как два массива и , где , если операция должна выполниться на машине в момент времени и , если машина простаивает в этот момент. Будем называть пустой операцией. И для каждой операции , выполняющейся на машине существует , для которого . Аналогично для . Расписание достижимо тогда и только тогда, когда из следует для некоторого , и первая операция для каждой работы запланирована на нужной машине. Перестановку всех операций будем называть списком. Для данный списка осуществимое расписание может быть создано следующим способом: планируем выполнять операции в порядке, соответствующим , причем каждую операцию стараемся выполнить как можно раньше. Подобное расписание будем называть соответствующим расписанием. — время окончания работы в достижимом расписании можно рассчитать как:
или — операция -той работы}
Задача заключается в том, что для данного каждой работе дедлайна мы хотим найти достижимое расписание с наименьшими максимальным временем опоздания:
Следующий алгоритм решает эту задачу:
- Введём для каждой операции величину
- Создадим список всех операций , упорядоченный в порядке неубывания значений
- Найдем соответствующее списку расписание.
Этот алгоритм может быть реализованным с асимптотикой . Однако, мы будем использовать эвристику с хешами и улучшим асимптотику алгоритма до .
Мы предполагаем, что для и хотя бы для одной работы . Иначе, вычтем из всех минимальное значение по
Так как для всех и справедливо как минимум для одной работы . К тому же, можно предположить, что . Таким образом, работы с , то есть c можно смело игнорировать. Они не влияют на значение улучшаемой функции , так как для некого Можно выполнять эти работы в любом порядке после всех остальных. Для оставшихся операций мы имеем:
Каждую операцию мы кладём в соответствующую корзину , где . На втором шаге мы планируем операции соответственно возрастающему по номеру корзины порядку, где операции из одной корзины могут выполнятся в произвольном порядке.
Алгоритм
Давайте детально рассмотрим алгоритм. и обозначают первый период времени , когда соответствующие машины и бездействуют. обозначает время окончания последней запланированной операции -той работы. — множество работ, где
main()
  for k: -r + 1 to r - 1
     = ;
    Z = ;
  for i: 1 to n
    if  < r
      for j: 1 to n_i
        добавить  в 
    else
      добавить работу i в Z
  for i: 1 to n
    LAST(i) = 0;
  T1 = 0;
  T2 = 0;
  for k: -r + 1 to r - 1
    while 
      Выбрать задание  из 
       = ;
      schedule() 
  while 
    Выбрать работу i из Z
    Z = ;
    for j: 1 to 
      schedule() 	
schedule() if == A if T1 < LAST(i) t = LAST(i) A(t) = else t = T1; A(t) = ; while T1 = T1 + 1; else if T2 < LAST(i) t = LAST(i) B(t) = else t = T2; A(t) = ; while T2 = T2 + 1; LAST(i) = t + 1
Очевидно, что количество шагов алгоритма ограничено
