Блог пользователя Um_nik

Автор Um_nik, 10 лет назад, По-русски

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

Имеется n деталей и два станка. Каждая деталь должна сначала пройти обработку на первом станке, затем — на втором. При этом i-ая деталь обрабатывается на первом станке за ai времени, а на втором — за bi времени. Каждый станок в каждый момент времени может работать только с одной деталью.

Требуется составить такой порядок подачи деталей на станки, чтобы итоговое время обработки всех деталей было бы минимальным.

Решение задачи описано на e-maxx.ru

Перед дальнейшим чтением рекомендую ознакомиться с приведенным там решением, здесь будут обсуждены некоторые его проблемы.

Опуская доказательства: в решении предлагается отсортировать пары чисел (ai, bi) следующим компаратором:

Мы определили некоторое бинарное отношение на множестве пар чисел. Внимание, вопрос: почему этим отношением можно пользоваться как компаратором?

Сначала о плюсах: Это отношение действительно транзитивно.

Давайте это докажем (если вы хотите минусов, эту часть можно пропустить).

Дано: min(a1, b2) < min(a2, b1), min(a2, b3) < min(a3, b2).

Доказать: min(a1, b3) < min(a3, b1)

Доказательство: от противного. Предположим min(a1, b3) ≥ min(a3, b1)

Есть два варианта:

1) a1 ≤ b2

Из этого следует a1 < a2, a1 < b1. Из нашего предположения получаем, что

Отсюда min(a1, b3) ≤ b3 < min(a3, b1)

2) a1 > b2

Из этого следует b2 < a2, b2 < b1.

Отсюда min(a1, b3) ≤ b3 < min(a3, b1)

Получили противоречие.

Ч.т.д.

А вот теперь о минусах. Очевидно, это отношение не обладает свойством антисимметричности. Более того: Давайте на множестве пар чисел введем отношение "быть равными" в том смысле, что ни одна из пар не больше другой. . Это отношение транзитивным не является!

Пример: (2, 3) = (1, 1) = (4, 5), но (2, 3) < (4, 5).

Справедливости ради: Можно показать, что если (a1, b1) = (a2, b2) = (a3, b3) и a2! = b2, то (a1, b1) = (a3, b3)

Давайте определим отсортированную последовательность так: Последовательность отсортирована по неубыванию, если для любых , т.е. никогда больший элемент не идет перед меньшим.

Построим ориентированный граф так: Вершины — элементы последовательности, дуга из i в j соответствует pi < pj. Тогда наше определение отсортированной последовательности совпадает с топологической сортировкой этого графа.

Мы показали, что ориентированных циклов в этом графе нет, а значит на нем есть топологическая сортировка, т.е. нашу последовательность можно отсортировать.

Но если мы просто передадим наш компаратор в пузырьковую сортировку, то последовательность не будет отсортирована.

Пример: (4, 5), (1, 1), (2, 3)

Думаю, что для остальных сортировок тоже несложно будет подобрать соответствующий пример (возможно, он будет зависеть от конкретной реализации, потому что все такие контрпримеры завязаны на обработке "равных" элементов).

Таким образом, доказательство на e-maxx не верно.

  • Проголосовать: нравится
  • +66
  • Проголосовать: не нравится

»
10 лет назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится

Возьмем все пары, где a <  = b и положим в начало в порядке возрастания a. Потом возьмем все пары, где a > b и положим в конец в порядке убывания b. Но доказательство все равно неправильное, оно гарантирует только локальный минимум, а не глобальный.

»
10 лет назад, # |
  Проголосовать: нравится -26 Проголосовать: не нравится

С двумя станками :DDDD

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится +83 Проголосовать: не нравится

»
7 лет назад, # |
  Проголосовать: нравится +25 Проголосовать: не нравится

Пусть тут будут лежать стресс и тесты против других сортировок

github: tests

github: solution, stress

  • »
    »
    5 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +43 Проголосовать: не нравится

    Привет, Burunduk1!

    Как замечено в посте, если бы не было $$$a_i = b_i$$$, то сортировка бы работала верно. Но что нам стоит от таких предметов избавиться?

    Можно просто мысленно увеличить все $$$b_i$$$ на $$$10^{-9}$$$. В таком случае компаратор работает, а мы получим ответ не более, чем на $$$10^{-9} * n$$$ хуже. Это меньше единицы, а значит если вернуться к целым числам, то ошибка меньше $$$1$$$ означает, что ошибки нет.

    TL;DR, я заменил в твоём коде

      auto less = [&]( int i, int j ){
          return min(a[i], b[j]) < min(a[j], b[i]);
      };
    

    на следующее:

      auto less = [&]( int i, int j ){
          return min(2 * a[i], 2 * b[j] + 1) < min(2 * a[j], 2 * b[i] + 1);
      };
    

    Стресс проходит.

    EDIT: на самом деле формально надо ещё доказать, что так можно :)

    (Обычно такие доказательства наначинаются со слов "допустим есть инверсия")