1sumwu — различия между версиями
Dominica (обсуждение | вклад) (→Время работы) |
м (rollbackEdits.php mass rollback) |
||
(не показано 10 промежуточных версий 2 участников) | |||
Строка 9: | Строка 9: | ||
В общем случае, когда времена выполнения работ <tex>p_i</tex> могут быть сколь угодно большими или, например, дробными, данная задача может быть решена с помощью перебора. | В общем случае, когда времена выполнения работ <tex>p_i</tex> могут быть сколь угодно большими или, например, дробными, данная задача может быть решена с помощью перебора. | ||
− | Будем перебирать все перестановки чисел от <tex>1</tex> до <tex>n</tex>, обозначающих номера заданий. При получении очередной перестановки просто будем пытаться выполнять задания в указанном порядке. Если значение <tex>\sum w_i U_i</tex>, полученное при данном расположении заданий, лучше, чем предыдущие результаты, то обновляем ответ. | + | Будем перебирать все перестановки чисел от <tex>1</tex> до <tex>n</tex>, обозначающих номера заданий. При получении очередной перестановки просто будем пытаться выполнять задания в указанном порядке. Если значение <tex>\sum \limits_{i=1}^n w_i U_i</tex>, полученное при данном расположении заданий, лучше, чем предыдущие результаты, то обновляем ответ. |
− | Данное решение будет работать за <tex>O(n \cdot n!)</tex>. | + | Данное решение будет работать за <tex> \mathcal{O}(n \cdot n!)</tex>. |
==Перебор с битовыми масками== | ==Перебор с битовыми масками== | ||
Строка 34: | Строка 34: | ||
Далее мы сортируем задания из этого списка по времени неубывания дедлайнов, а те задания, что не попали в этот список, должны быть отправлены в конец расписания в любом порядке. | Далее мы сортируем задания из этого списка по времени неубывания дедлайнов, а те задания, что не попали в этот список, должны быть отправлены в конец расписания в любом порядке. | ||
Далее проверяем полученное возможное расписание на корректность, и, в случае успеха, обновляем ответ. | Далее проверяем полученное возможное расписание на корректность, и, в случае успеха, обновляем ответ. | ||
− | Перебор всех масок может быть произведен за <tex>O(2 ^ n)</tex>, и <tex>O(n)</tex> на пересчет ответа. Таким образом, это решение будет работать за <tex>O(n \cdot 2^n)</tex>. | + | |
+ | Перебор всех масок может быть произведен за <tex>\mathcal{O}(2 ^ n)</tex>, и <tex>\mathcal{O}(n)</tex> на пересчет ответа. Таким образом, это решение будет работать за <tex>\mathcal{O}(n \cdot 2^n)</tex>. | ||
==Псевдополиномиальное решение== | ==Псевдополиномиальное решение== | ||
Строка 66: | Строка 67: | ||
* В массиве <tex>w[i] </tex> хранятся стоимости выполнения работ, в <tex>d[i] </tex> {{---}} дедлайны, а в <tex>p[i] </tex> {{---}} продолжительности выполнения. | * В массиве <tex>w[i] </tex> хранятся стоимости выполнения работ, в <tex>d[i] </tex> {{---}} дедлайны, а в <tex>p[i] </tex> {{---}} продолжительности выполнения. | ||
− | '''function''' <tex> getAnswer(p : </tex> '''int''' <tex>[n],</tex> <tex> w : </tex> '''int''' <tex>[n],</tex> <tex> d : </tex> '''int''' <tex>[n] ):</tex> '''int''' | + | '''function''' <tex> \mathrm{getAnswer}(p : </tex> '''int'''<tex>\mathbf{[n]},</tex> <tex> w : </tex> '''int'''<tex>\mathbf{[n]},</tex> <tex> d : </tex> '''int'''<tex>\mathbf{[n]} ):</tex> '''int''' |
'''int''' <tex>T = 0 </tex> | '''int''' <tex>T = 0 </tex> | ||
'''for''' <tex>i = 1 .. n</tex> | '''for''' <tex>i = 1 .. n</tex> | ||
<tex>T = T + p[i]</tex> | <tex>T = T + p[i]</tex> | ||
'''int''' <tex>F[][]</tex> | '''int''' <tex>F[][]</tex> | ||
− | сортируем работы по неубыванию времен дедлайнов <tex>d[i]</tex> | + | сортируем работы по неубыванию времен дедлайнов <tex>d[i]</tex> |
'''for''' <tex>t = -p_{max}</tex> '''to''' <tex>-1</tex> | '''for''' <tex>t = -p_{max}</tex> '''to''' <tex>-1</tex> | ||
'''for''' <tex>j = 0</tex> '''to''' <tex>n</tex> | '''for''' <tex>j = 0</tex> '''to''' <tex>n</tex> | ||
Строка 88: | Строка 89: | ||
Для того, чтобы найти само расписание, по доказанной выше лемме, нам достаточно найти множество работ <tex>L</tex>, которые будут выполнены с опозданием. Это может быть сделано следующим способом: | Для того, чтобы найти само расписание, по доказанной выше лемме, нам достаточно найти множество работ <tex>L</tex>, которые будут выполнены с опозданием. Это может быть сделано следующим способом: | ||
− | '''function''' <tex> | + | '''function''' <tex> \mathrm{getLate}(F : </tex> '''int'''<tex>\mathbf{[n][p_{max}]},</tex> <tex> p : </tex> '''int'''<tex>\mathbf{[n]},</tex> <tex> w : </tex> '''int'''<tex>\mathbf{[n]},</tex> <tex> d : </tex> '''int'''<tex>\mathbf{[n]} ):</tex> '''set<int>''' |
'''int''' <tex>t = d[n]</tex> | '''int''' <tex>t = d[n]</tex> | ||
'''set<int>''' <tex>L = \varnothing</tex> | '''set<int>''' <tex>L = \varnothing</tex> | ||
Строка 98: | Строка 99: | ||
<tex> t = t - p[j] </tex> | <tex> t = t - p[j] </tex> | ||
'''return''' <tex>L</tex> | '''return''' <tex>L</tex> | ||
+ | Согласно лемме, само расписание будет состоять из работ, не попавших в <tex>L</tex>, отсортированных по неубыванию <tex>d_i</tex> и работ из <tex>L</tex>, записанных в конец в любом порядке. | ||
===Время работы=== | ===Время работы=== | ||
− | В функции <tex>getAnswer | + | В функции <tex>\mathrm{getAnswer}</tex> пересчет динамики происходит за <tex> \mathcal{O}(n T)</tex>, а функция <tex>\mathrm{getLate}</tex> восстанавливает список просроченных работ за <tex> \mathcal{O}(n)</tex>. Дальнейшее восстановление расписания происходит в худшем случае за <tex> \mathcal{O}(n \log n)</tex>. Отсюда видно, что время работы приведенного выше алгоритма {{---}} <tex> \mathcal{O}\Big(n \sum\limits_{i=1}^n p_i\Big)</tex>. |
==См. также == | ==См. также == | ||
Строка 111: | Строка 113: | ||
* P. Brucker. Scheduling Algorithms (2006), 5th edition, стр. 26 - 28 | * P. Brucker. Scheduling Algorithms (2006), 5th edition, стр. 26 - 28 | ||
− | [[Категория: | + | [[Категория: Алгоритмы и структуры данных]] |
[[Категория: Теория расписаний]] | [[Категория: Теория расписаний]] |
Текущая версия на 19:17, 4 сентября 2022
Задача: |
Есть один станок и | работ. Для каждой работы заданы время выполнения дедлайн и стоимость выполнения этой работы . Необходимо минимизировать .
Содержание
Наивное решение
В общем случае, когда времена выполнения работ
могут быть сколь угодно большими или, например, дробными, данная задача может быть решена с помощью перебора.Будем перебирать все перестановки чисел от
до , обозначающих номера заданий. При получении очередной перестановки просто будем пытаться выполнять задания в указанном порядке. Если значение , полученное при данном расположении заданий, лучше, чем предыдущие результаты, то обновляем ответ.Данное решение будет работать за
.Перебор с битовыми масками
Далее широко будет использоваться следующий факт:
Лемма: |
Пусть все работы отсортированы в порядке неубывания дедлайнов .
Тогда существует оптимальное расписание вида , такое, что — номера работ, которые успеют выполниться вовремя, а — номера просроченных работ. |
Доказательство: |
Пусть у нас есть некоторое оптимальное раписание . Получим необходимое нам расписание путем переставления некоторых работ.
|
Наше решение будет построено на переборе всех битовых масок. При построении решения мы будем опираться на доказанную лемму.
Если бит, соответствующий заданию с номером
равен , то это задание должно быть записано в список заданий, которые, возможно, успеют выполниться. Далее мы сортируем задания из этого списка по времени неубывания дедлайнов, а те задания, что не попали в этот список, должны быть отправлены в конец расписания в любом порядке. Далее проверяем полученное возможное расписание на корректность, и, в случае успеха, обновляем ответ.Перебор всех масок может быть произведен за
, и на пересчет ответа. Таким образом, это решение будет работать за .Псевдополиномиальное решение
В ситуации, когда времена выполнения работ динамическое программирование.
целочисленные, а значение не очень большое, то для решения данной задачи можно применитьОписание алгоритма
Обозначим
. Для всех и будем рассчитывать — значение целевой функции , при условии, что были рассмотрены первые работ и общее время выполнения тех из них, что будут закончены вовремя, не превышает времени .- Если и работа успевает выполниться вовремя в расписании, соответствующем , то , иначе .
- Если , то , поскольку все работы с номерами , законченные позже, чем , будут выполнены с опозданием.
Отсюда, получим соотношение:
В качестве начальных условий следует взять
при и при .Ответом на задачу будет
.Псевдокод
Приведенный ниже алгоритм вычисляет
для и .- За обозначим самое большое из времен выполнения заданий.
- Значения будем хранить в массиве .
- В массиве хранятся стоимости выполнения работ, в — дедлайны, а в — продолжительности выполнения.
functionint int int int int for int сортируем работы по неубыванию времен дедлайнов for to for to for to for to for to if else for to return
Для того, чтобы найти само расписание, по доказанной выше лемме, нам достаточно найти множество работ
, которые будут выполнены с опозданием. Это может быть сделано следующим способом:functionint int int int set<int> int set<int> for downto if else return
Согласно лемме, само расписание будет состоять из работ, не попавших в
, отсортированных по неубыванию и работ из , записанных в конец в любом порядке.Время работы
В функции
пересчет динамики происходит за , а функция восстанавливает список просроченных работ за . Дальнейшее восстановление расписания происходит в худшем случае за . Отсюда видно, что время работы приведенного выше алгоритма — .См. также
Источники информации
- P. Brucker. Scheduling Algorithms (2006), 5th edition, стр. 26 - 28