R2Cmax — различия между версиями
Novik (обсуждение | вклад) (→Эффективное решение) |
м (rollbackEdits.php mass rollback) |
||
(не показано 6 промежуточных версий 3 участников) | |||
Строка 5: | Строка 5: | ||
и втором станке различное. Нужно минимизировать время завершения всех работ.}} | и втором станке различное. Нужно минимизировать время завершения всех работ.}} | ||
− | Задача <tex>R2 \mid \mid C_{max}</tex> является <tex>\mathrm{NP}</tex>-полной задачей. | + | Задача <tex>R2 \mid \mid C_{max}</tex> является [[Классы_NP_и_Σ₁#def1|<tex>\mathrm{NP}</tex>-полной задачей]]<ref> J.K. Lenstra, A.H.G. Rinnooy Kan, and P. Brucker. Complexity of machine scheduling problems. Annals of Discrete Mathematics, 1:343–362, 1977.</ref>. |
==Неэффективное решение== | ==Неэффективное решение== | ||
Строка 15: | Строка 15: | ||
Применим для решения данной задачи [[Динамическое программирование|динамическое программирование]]. | Применим для решения данной задачи [[Динамическое программирование|динамическое программирование]]. | ||
− | Будем считать массив <tex>dp[i][j]</tex>, в котором будем хранить минимально время выполнения работ на втором станке, где <tex>i</tex> означает, что мы рассмотрели <tex>i</tex> работ, а <tex>j</tex> с каким временем выполнения работ на первом станке. Тогда <tex>j</tex> не превосходит суммы выполнения работ на первом станке. | + | Будем считать массив <tex>dp[i][j]</tex>, в котором будем хранить минимально время выполнения работ на втором станке, где <tex>i</tex> означает, что мы рассмотрели <tex>i</tex> работ, а <tex>j</tex> {{---}} с каким временем выполнения работ на первом станке. Тогда <tex>j</tex> не превосходит суммы выполнения работ на первом станке. Назовем эту сумму <tex>maxTime</tex>. |
Изначальное значение <tex>dp[0][0] = 0</tex>, а всё остальную таблицу проинициализируем бесконечностью. | Изначальное значение <tex>dp[0][0] = 0</tex>, а всё остальную таблицу проинициализируем бесконечностью. | ||
− | Допустим мы посчитали динамику для <tex>i</tex> работ. Теперь надо пересчитать её для <tex>(i + 1)</tex>-ой работы. Переберём время выполнения работ на первом станке и посчитаем какое минимально время выполнения мы можем получить | + | Допустим мы посчитали динамику для <tex>i</tex> работ. Теперь надо пересчитать её для <tex>(i + 1)</tex>-ой работы. Переберём время выполнения работ на первом станке и посчитаем какое минимально время выполнения мы можем получить на втором станке при фиксированном времени на первом. Так как <tex>(i + 1)</tex>-ю работу мы можем выполнить либо на первом станке, либо на втором, то <tex> dp[i + 1][j]</tex> надо прорелаксировать значением <tex>dp[i][j - p_1[i + 1]] </tex>, что соответсвует выполнению работы на первом станке, и значением <tex> dp[i][j]+p_2[i + 1]</tex> (выполнение на втором станке). |
− | Таким образом: | + | Таким образом: |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | <tex>dp[i + 1][j] = \min(dp[i][j] + p_2[i + 1], dp[i][j - p_1[i + 1]])</tex> | |
− | + | Тогда ответом на задачу будет <tex>\min\limits_{j}(\max(j, dp[n][j]))</tex>. Другими словами мы перебираем время работы на первом станке и смотрим сколько ещё потребуется работать на втором станке. Время выполнения всех работ {{---}} это максимум из этих двух величин. И в конце из всех времен выбираем минимальное. | |
+ | |||
+ | Также можно заметить, что во время каждой итерации алгоритма используется только два столбца массива <tex> dp </tex>. Это позволяет уменьшить использование памяти с <tex>O(n \cdot maxTime)</tex> до <tex> O(maxTime)</tex>. | ||
==Доказательство корректности алгоритма== | ==Доказательство корректности алгоритма== | ||
Строка 41: | Строка 37: | ||
Корректность расписания, составленного алгоритмом очевидна. Надо доказать его оптимальность. | Корректность расписания, составленного алгоритмом очевидна. Надо доказать его оптимальность. | ||
− | Пусть расписание, составленное этим алгоритмом <tex>S</tex> не оптимальное | + | Пусть расписание, составленное этим алгоритмом <tex>S</tex> не оптимальное и в конце работы алгоритма минимум достигается в <tex>\max(time, d[n][time])</tex>. Рассмотрим оптимальное решение <tex>O</tex>. |
Рассмотрим произвольную работу, выполненную на первом станке в оптимальном расписании, но на втором в расписании, составленном алгоритмом. Пусть у этой работы номер <tex>i</tex>. Если её выполнить на первом станке, то время окончания всех работ будет <tex>\max(time + p_{1}[i], d[n][time + p_{1}[i]])</tex>. Однако <tex>\max(time, d[n][time]) \leqslant \max(time + p_{1}[i], d[n][time + p_{1}[i]])</tex> | Рассмотрим произвольную работу, выполненную на первом станке в оптимальном расписании, но на втором в расписании, составленном алгоритмом. Пусть у этой работы номер <tex>i</tex>. Если её выполнить на первом станке, то время окончания всех работ будет <tex>\max(time + p_{1}[i], d[n][time + p_{1}[i]])</tex>. Однако <tex>\max(time, d[n][time]) \leqslant \max(time + p_{1}[i], d[n][time + p_{1}[i]])</tex> | ||
Строка 51: | Строка 47: | ||
==Псевдокод== | ==Псевдокод== | ||
− | <font color=green>//Функция принимает количество работ n, список времён выполнения работ на первом станке p1 и времён выполнения на втором станке p2.<br>//Функция возвращает минимальное время выполнения всех работ на двух станках.</font> | + | <font color=green>// Функция принимает количество работ n, список времён выполнения работ на первом станке p1 и времён выполнения на втором станке p2.<br>// Функция возвращает минимальное время выполнения всех работ на двух станках.</font> |
− | + | '''function''' getCmax(p1 : '''int'''[n], p2 : '''int'''[n]): '''int''' | |
− | + | '''int''' maxTime = 0 | |
− | + | '''for''' i = 0 .. n - 1 | |
− | + | maxTime += p1[i] | |
− | + | '''int'''[][] dp | |
− | + | fill(dp, <tex>\infty</tex>) | |
− | + | dp[0][0] = 0 | |
− | + | '''for''' i = 0 .. n - 1 | |
− | + | '''for''' j = 0 .. maxTime | |
− | + | dp[i + 1][j] = min(dp[i][j - p1[i + 1]], dp[i][j] + p2[i + 1]) | |
− | + | '''int''' answer = <tex>\infty</tex> | |
− | + | '''for''' j = 0 .. maxTime | |
− | + | answer = min(answer, max(j, dp[n][j])) | |
− | + | '''return''' answer | |
− | |||
− | |||
==Время работы== | ==Время работы== | ||
Время работы <tex>O(n \cdot maxTime)</tex> {{---}} псевдополиномиальный алгоритм. Кроме того, если время выполнения работ, будет вещественные числа, то придется приводить их до целых, либо считать приблежённое значения. | Время работы <tex>O(n \cdot maxTime)</tex> {{---}} псевдополиномиальный алгоритм. Кроме того, если время выполнения работ, будет вещественные числа, то придется приводить их до целых, либо считать приблежённое значения. | ||
− | |||
− | |||
− | |||
==См. также== | ==См. также== | ||
* [[F2Cmax|<tex>F2\mid\mid C_{max}</tex>]] | * [[F2Cmax|<tex>F2\mid\mid C_{max}</tex>]] | ||
* [[O2Cmax|<tex>O2\mid\mid C_{max}</tex>]] | * [[O2Cmax|<tex>O2\mid\mid C_{max}</tex>]] | ||
+ | |||
+ | ==Примечания== | ||
+ | <references/> | ||
+ | |||
+ | ==Источники информации== | ||
+ | * J.K. Lenstra, A.H.G. Rinnooy Kan, and P. Brucker. Complexity of machine scheduling problems. Annals of Discrete Mathematics, стр. 358–360, 1977. | ||
[[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
[[Категория: Теория расписаний]] | [[Категория: Теория расписаний]] |
Текущая версия на 19:25, 4 сентября 2022
Задача: |
Дано два разных неоднородных станка, которые работают параллельно. Есть | работ, время выполнения которых на первом и втором станке различное. Нужно минимизировать время завершения всех работ.
Задача является -полной задачей[1].
Содержание
Неэффективное решение
Переберём все битовые маски длины
. Для каждой маски вычислим завершение последней работы. Работы будем выполнять следующим образом, если на -й позиции стоит , то -ая работа будет выполняться на первом станке, иначе на втором. Среди всех масок выберем ту, у которой минимальный.Время работы алгоритма
Эффективное решение
Применим для решения данной задачи динамическое программирование.
Будем считать массив
, в котором будем хранить минимально время выполнения работ на втором станке, где означает, что мы рассмотрели работ, а — с каким временем выполнения работ на первом станке. Тогда не превосходит суммы выполнения работ на первом станке. Назовем эту сумму .Изначальное значение
, а всё остальную таблицу проинициализируем бесконечностью.Допустим мы посчитали динамику для
работ. Теперь надо пересчитать её для -ой работы. Переберём время выполнения работ на первом станке и посчитаем какое минимально время выполнения мы можем получить на втором станке при фиксированном времени на первом. Так как -ю работу мы можем выполнить либо на первом станке, либо на втором, то надо прорелаксировать значением , что соответсвует выполнению работы на первом станке, и значением (выполнение на втором станке).Таким образом:
Тогда ответом на задачу будет
. Другими словами мы перебираем время работы на первом станке и смотрим сколько ещё потребуется работать на втором станке. Время выполнения всех работ — это максимум из этих двух величин. И в конце из всех времен выбираем минимальное.Также можно заметить, что во время каждой итерации алгоритма используется только два столбца массива
. Это позволяет уменьшить использование памяти с до .Доказательство корректности алгоритма
Теорема: |
Расписание, построенное данным алгоритмом, является корректным и оптимальным. |
Доказательство: |
Корректность расписания, составленного алгоритмом очевидна. Надо доказать его оптимальность. Пусть расписание, составленное этим алгоритмом не оптимальное и в конце работы алгоритма минимум достигается в . Рассмотрим оптимальное решение .Рассмотрим произвольную работу, выполненную на первом станке в оптимальном расписании, но на втором в расписании, составленном алгоритмом. Пусть у этой работы номер . Если её выполнить на первом станке, то время окончания всех работ будет . ОднакоРассмотрим произвольную работу, выполненную в оптимальном расписании на втором станке, но на первом в расписании, составленном алгоритмом. Пусть номер этой работы В итоге если превратить решение . Если выполнять эту работу на втором станке, то время выполнения всех работ будет . Но . в решение эквивалентное , то ответ не будет превосходить ответ . Тогда расписание оптимальное. |
Псевдокод
// Функция принимает количество работ n, список времён выполнения работ на первом станке p1 и времён выполнения на втором станке p2.
// Функция возвращает минимальное время выполнения всех работ на двух станках. function getCmax(p1 : int[n], p2 : int[n]): int int maxTime = 0 for i = 0 .. n - 1 maxTime += p1[i] int[][] dp fill(dp, ) dp[0][0] = 0 for i = 0 .. n - 1 for j = 0 .. maxTime dp[i + 1][j] = min(dp[i][j - p1[i + 1]], dp[i][j] + p2[i + 1]) int answer = for j = 0 .. maxTime answer = min(answer, max(j, dp[n][j])) return answer
Время работы
Время работы
— псевдополиномиальный алгоритм. Кроме того, если время выполнения работ, будет вещественные числа, то придется приводить их до целых, либо считать приблежённое значения.См. также
Примечания
- ↑ J.K. Lenstra, A.H.G. Rinnooy Kan, and P. Brucker. Complexity of machine scheduling problems. Annals of Discrete Mathematics, 1:343–362, 1977.
Источники информации
- J.K. Lenstra, A.H.G. Rinnooy Kan, and P. Brucker. Complexity of machine scheduling problems. Annals of Discrete Mathematics, стр. 358–360, 1977.