Когда вы складываете книги, вы обычно хотите, чтобы самые большие были внизу, а самые маленькие - вверху. Однако, мое скрытое ОКР заставляет меня чувствовать себя неловко, если у меня есть две книги, одна из которых короче (по высоте), но шире другой. Независимо от того, в каком порядке я их размещаю, верхняя книга будет выходить за нижнюю книгу с одной стороны.
В качестве примера, скажем, одна книга имеет размеры, (10,15)
а другая имеет размеры (11,14)
. Независимо от того, какой путь я поставлю, я получаю навес. Но если у меня есть книги с размерами (4,3)
и (5,6)
, я могу избежать нависания, поместив последний ниже первого.
Для целей этой задачи мы рассмотрим свесы только в отношении книги, приведенной ниже . Например , если у меня есть стек (5,5)
, (3,3)
, (4,4)
(не то, что любой нормальный человек будет делать это), то верхняя книга считается как козырьком, хотя и не выходит за пределы нижней книги. Точно так же, стек (3,3)
, (3,3)
, (4,4)
также имеет только один выступ, несмотря на верхних книги , выходящих за пределами нижней.
Соревнование
По заданному списку целочисленных пар для размеров книг отсортируйте эти пары / книги таким образом, чтобы количество выступов было минимальным. Вы не должны вращать книги - я хочу, чтобы все шипы стояли в одном направлении. Если существует несколько решений с одинаковым количеством свесов, вы можете выбрать любой такой порядок. Ваш алгоритм сортировки не должен быть стабильным. Ваша реализация может предполагать, что размеры книги меньше 2 16 каждый.
Временная сложность. Чтобы сделать это немного интереснее, асимптотическая сложность алгоритма в худшем случае должна быть полиномиальной по размеру стека. Таким образом, вы не можете просто проверить каждую возможную перестановку. Пожалуйста, включите краткое доказательство оптимальности и сложности вашего алгоритма и, возможно, график, который показывает масштабирование для больших случайных входов. Конечно, вы не можете использовать максимальный размер ввода в качестве аргумента, который ваш код запускает в O (1).
Вы можете написать программу или функцию, получить ввод через STDIN, ARGV или аргумент функции в любом удобном (не предварительно обработанном) формате списка и либо распечатать, либо вернуть результат.
Это код гольф, поэтому самый короткий ответ (в байтах) выигрывает.
Я уверен, что существует полиномиальное решение, но если вы можете доказать, что я неправ, вы можете представить такое доказательство вместо представления в гольф. В этом случае вы можете предположить, что P ≠ NP . Я приму первое правильное доказательство и вознаградлю его за это.
Примеры
In: [[1, 1], [10, 10], [4, 5], [7, 5], [7, 7], [10, 10], [9, 8], [7, 5], [7, 5], [3, 1]]
Out: [[10, 10], [10, 10], [9, 8], [7, 7], [7, 5], [7, 5], [7, 5], [4, 5], [3, 1], [1, 1]]
In: [[4, 5], [5, 4], [5, 4], [5, 4], [5, 4], [4, 5], [4, 5], [4, 5], [5, 4], [4, 5]]
Out: [[4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [5, 4], [5, 4], [5, 4], [5, 4], [5, 4]]
or [[5, 4], [5, 4], [5, 4], [5, 4], [5, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5]]
In: [[2, 3], [1, 1], [5, 5], [7, 1]]
Out: [[5, 5], [2, 3], [7, 1], [1, 1]]
or [[5, 5], [2, 3], [1, 1], [7, 1]]
or [[7, 1], [5, 5], [2, 3], [1, 1]]
or [[7, 1], [1, 1], [5, 5], [2, 3]]
Я создал их вручную, поэтому дайте мне знать, если вы заметите какие-либо ошибки.
источник
Ответы:
Пиф , 30
Это прямой гольф потрясающего алгоритма GRC. Вот точный эквивалент вышеупомянутой программы pyth в ее скомпилированном коде python.
В этом контексте
Psum(Y)
функция эквивалентна питонуsum(Y,[])
.Фактический скомпилированный и запущенный код (из
pyth -d
):источник
sum(Y,[])
. Все это должно работать в Pyth, просто перевод не включает его автоматически.Pprint("\n",Psum(Y))
. Я думаю, что он, возможно, упростил это для удобства, наряду со всеми-1
s и т. Д. НаPsum
самом деле будет работать больше какreduce(lambda x,y:x+y, Y[1:], Y[0])
.Python, 113
После сортировки списка книг в порядке убывания (сначала по ширине, а затем по высоте) книги разбиваются на стопки без наложений. Чтобы определить, где разместить каждую книгу, ее высота сравнивается с высотой верхней книги в каждой стопке. Он помещается в первую возможную кучу, или же создается новая куча.
Я не очень хорошо справляюсь со сложностью времени, но я считаю, что это будет наихудший случай O ( N 2 ). Есть два цикла , каждый из которых имеет не более N итераций. Я также использую встроенную сортировку Python, которая является O ( n log n ).
Мое первое доказательство того, что этот алгоритм дает оптимальные решения, оказалось неверным. Огромное спасибо @xnor и @ Sp3000 за отличную дискуссию в чате о том, как это доказать (которую вы можете прочитать, начиная здесь ). Разработав правильное доказательство, @xnor обнаружил, что часть его уже была сделана ( теорема Дилворта ).
В любом случае, вот обзор доказательства (спасибо @xnor и @ Sp3000).
Во-первых, мы определяем понятие antipile, или antihain ( цитата из @xnor ):
Затем мы сортируем книги в порядке убывания по их ширине (первая) и их высоте (вторая) *.
Для каждой книги B мы делаем следующее:
Теперь мы создали ссылку из каждой книги (кроме тех, что в первой стопке) на книгу в предыдущей стопке, которая больше по ширине и меньше по высоте.
Отличная диаграмма @ Sp3000 хорошо иллюстрирует это:
Следуя по любому пути от последней кучи (справа) до первой кучи (слева), мы получаем антипиле. Важно отметить, что длина этой стопки равна количеству стопок. Следовательно, количество используемых свай минимально.
Наконец, поскольку мы организовали книги в минимальное количество стопок без перекрытий, мы можем сложить их друг на друга, чтобы получить одну стопку с минимальным количеством перекрытий.
* этот полезный комментарий объясняет несколько вещей
источник