Сортувати стек книг


21

Під час складання книг зазвичай потрібно покласти найбільші внизу, а найменші - вгорі. Однак мій прихований OCD змушує мене почувати себе дуже неприємно, якщо у мене є дві книги, де одна коротша (на зріст), але ширша за іншу. Незалежно від того, в якому порядку я їх розміщую, головна книга буде виходити за межі нижньої книги з одного боку.

Наприклад, скажімо, що одна книга має розміри, (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]]

Я створив їх вручну, тому повідомте мені, якщо ви помітили якісь помилки.


3
Ви впевнені, що пошук рішення з мінімальною кількістю накидів може бути вирішений за багаточлен?
COTO

@COTO Я досить впевнений, так.
Мартін Ендер

Хм. Зазвичай я вирішую це з жадібним алгоритмом, але я можу легко придбати вхідні дані, що ведуть до неоптимальних результатів за будь-яким критерієм "жадібності", який я можу придумати (наприклад, область, максимізація одного виміру, максимізація найменшого розміру тощо). Єдиний інший підхід, який я можу подумати, полягає у розподілі книг на кліки, і всі вони мають експоненціальну найгіршу складність. Мені буде цікаво подивитися, які відповіді виходять. Ви також можете попросити короткий доказ оптимальності сортування як частини специфікації.
COTO

@COTO Я додав аб цьому абзац, якщо я насправді помиляюся, але на це не розраховуйте. ;)
Мартін Ендер

На всякий випадок потенційні докази того, що не існує алгоритму поліноміального часу, повинні дозволяти вважати, що P не дорівнює NP.
xnor

Відповіді:


2

Піт , 30

FN_SQFbYIgeeYeb~b]NB)E~Y]]N;sY

Це прямий гольф алгоритму grc. Ось точний еквівалент вищезгаданої програми pyth, у складеному пітонному коді.

Q = eval(input())
Y = []
for N in sorted(Q)[::-1]:
     for b in Y:
         if Y[-1][-1] >= b[-1]:
             b += [N]
             break
     else:
         Y += [[N]]
print(Psum(Y))

У цьому контексті Psum(Y)функція еквівалентна пітону sum(Y,[]).

Фактично складений та запущений код (від pyth -d):

Y=[]
Q=copy(eval(input()))
for N in neg(Psorted(Q)):
 for b in Y:
  if gte(end(end(Y)),end(b)):
   b+=[N]
   break
 else:
  Y+=[[N]]
Pprint("\n",Psum(Y))

1
Для перекладу Python потрібно "Y = []", видаліть eval, якщо ви перебуваєте в Python 2, і для суми потрібен другий аргумент sum(Y,[]). Це все повинно працювати в Pyth, просто переклад не включає його автоматично.
xnor

@xnor Останній рядок дійсно говорить: Pprint("\n",Psum(Y)). Я думаю, що він, можливо, спростив це для зручності разом із усіма -1т. Д. PsumНасправді працював би більше, як reduce(lambda x,y:x+y, Y[1:], Y[0]).
FryAmTheEggman

20

Пітона, 113

P=[]
for n in sorted(input())[::-1]:
 for p in P:
  if p[-1][1]>=n[1]:p+=[n];break
 else:P+=[[n]]
print sum(P,[])

Після сортування списку книг у порядку зменшення (спочатку по ширині, а потім по висоті) це розділяє книги на палі без накладень. Щоб визначити, де розмістити кожну книгу, її висота порівнюється з висотою верхньої книги в кожній купі. Він розміщується на першій купі, можливо, інакше створюється нова ворс.

Я не дуже хороший із часовою складністю, але я вважаю, що це було б в гіршому випадку O ( N 2 ). Є дві петлі, кожна з яких має щонайбільше N ітерацій. Я також використовую вбудований сорт Python, який є O ( n log n ).


Мій перший доказ того, що цей алгоритм виробляє оптимальні рішення, виявився невірним. Величезна подяка надходить @xnor та @ Sp3000 за чудову дискусію у чаті про доведення цього (яку ви можете прочитати, починаючи тут ). Опрацювавши правильний доказ, @xnor виявив, що частина цього вже була зроблена ( теорема Ділворта ).

Ось огляд доказів у будь-якому разі (заслуга @xnor та @ Sp3000).

Спочатку ми визначаємо поняття антипіл, або антихаїн, ( цитується з @xnor ):

Антипіл - це послідовність книг зменшення висоти, але збільшення ширини.
Отже, кожна наступна книга суворо вища, але суворо менш широка.
Зверніть увагу, що будь-яка книга в антипілі нависає над будь-якою іншою книгою в антипілі.
Отже, жодна дві книги в межах антипіля не можуть бути в одній купі.
Як наслідок, якщо ви можете знайти антипіль x книг, то ці книги повинні бути в різних палі.
Отже, розмір найбільшої антипіли є нижньою межею на кількість паль

Потім сортуємо книги у порядку зменшення за їх шириною (перше) та висотою (друге) *.

Для кожної книги B робимо наступне:

  1. Якщо B може поміститися на першу купу, ми поміщаємо її туди і рухаємось далі.
  2. В іншому випадку ми знаходимо найраніший * ворс х, який B можна розмістити зверху. Це може бути нова купка при необхідності.
  3. Далі пов'язуємо B до P , де P - верхня книга на попередній купі x - 1 .
  4. Зараз ми знаємо, що:
    • B суворо * менша ширина, ніж Р , оскільки книги сортуються у порядку зменшення за шириною
    • B суворо більший за висотою, ніж P , інакше ми би розмістили B поверх P

Тепер ми побудували посилання з кожної книги (крім тієї, що знаходиться в першій групі), на книгу в попередній купі, яка має ширину і меншу висоту.

Чудова діаграма @ Sp3000 це добре ілюструє:

Дотримуючись будь-який шлях від останньої купи (праворуч), до першої палі (зліва), ми отримуємо антипіль. Важливо, що ця довжина антипіля дорівнює кількості паль. Отже, кількість використовуваних паль мінімальна.

Нарешті, оскільки ми організували книги в мінімальну кількість паль без перекриттів, ми можемо складати їх один на одного, щоб отримати одну купу з мінімальною кількістю перекриттів.

* Цей корисний коментар пояснює кілька речей


3
+1 для експозиційного доказу та посилання на дискусію. Реквізити для xnor та ін.
COTO

Я повинен уточнити, що теорема Ділворта не охоплює всього доказу, лише той факт, що найменша кількість паль дорівнює антипілу найбільшого розміру.
xnor
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.