책 스택 정렬


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 저는 확신합니다. 예.
Martin Ender

흠. 나는 일반적으로 탐욕스러운 알고리즘으로 문제를 해결할 것이지만, 내가 얻을 수있는 "탐욕스러운"기준 (예 : 면적, 한 차원을 최대화하고 가장 작은 차원을 최대화하는 등)에 대해 차선책의 결과를 초래하는 입력을 쉽게 조달 할 수 있습니다. 내가 생각할 수있는 유일한 다른 접근법은 책을 파쇄로 나누는 것과 관련이 있으며, 모든 책은 기하 급수적으로 최악의 복잡성을 가지고 있습니다. 어떤 답변이 나오는지 궁금합니다. 스펙의 일부로 정렬의 최적성에 대한 간략한 증거를 요청할 수도 있습니다.
COTO

@ COTO 나는 실제로 틀렸을 때를 위해 이것에 관한 단락을 추가했지만, 그것을 의지하지 않습니다. ;)
Martin Ender

다항식 시간 알고리즘이 존재하지 않는다는 잠재적 증거는 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)함수는 python과 같습니다 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
파이썬 번역에는 "Y = []"가 필요하고, 파이썬 2에 있다면 eval을 제거하고, 합에는 두 번째 인수가 필요합니다 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 개의 반복이있는 두 개의 루프가 있습니다 . 나는 또한 파이썬의 내장 정렬 사용 O를 ( N 로그 N ).


이 알고리즘이 최적의 솔루션을 생성한다는 첫 번째 증거는 잘못된 것으로 판명되었습니다. 이것을 증명하는 것에 대한 대화에서 위대한 토론에 대해 @xnor와 @ Sp3000에게 큰 감사를 전합니다 ( 여기에서 시작할 수 있습니다 ). 올바른 증거를 제시 한 후 @xnor는 그 일부가 이미 완료되었음을 발견했습니다 ( Dilworth 's theorem ).

어쨌든 증명에 대한 개요는 다음과 같습니다 (@xnor 및 @ Sp3000에 대한 신용).

먼저, 우리는 antipile 또는 antichain이라는 개념을 정의합니다 ( @xnor에서 인용 ) :

antipile 높이를 감소하지만, 폭 증가 책의 순서입니다
그래서, 각각의 연속이 책은 엄격하게 키가 있지만 확실히 작은 폭
참고 있다는 antipile의 다른 책을 통해 antipile 오버행의 모든 책은
antipile 캔 이내에, 두 개의 책 없습니다 같은 더미에있을
당신이 X 도서의 antipile을 찾을 수 있다면, 결과적으로 다음, 그 책은 다른 더미에 있어야합니다
그래서, 가장 큰 antipile의 크기가 더미의 수에 하한입니다

그런 다음 책을 너비 (첫 번째)와 높이 (초) *로 내림차순으로 정렬합니다.

각 책 B 에 대해 다음과 같이합니다.

  1. B 가 첫 번째 파일에 맞을 수 있으면 B 를 배치합니다.
  2. 그렇지 않으면, 우리는 B 가 위에 놓일 수있는 가장 빠른 * 파일 x 를 찾습니다 . 필요한 경우 새 파일이 될 수 있습니다.
  3. 다음으로 BP에 연결합니다 . 여기서 P 는 이전 파일 x-1 의 최상위 책입니다 .
  4. 우리는 지금 그것을 알고 있습니다 :
    • 책은 너비별로 내림차순으로 정렬되므로 BP 보다 너비가 엄격하게 * 작습니다.
    • B는 높이보다 엄격하게 더 큰 P , 또는 우리는 배치했을 B를 상단에 P

이제 우리는 모든 책 (첫 번째 파일의 책을 제외하고)에서 너비가 크고 높이가 낮은 이전 파일의 책으로 연결되는 링크를 구성했습니다.

@ Sp3000의 우수한 다이어그램은 이것을 잘 보여줍니다.

마지막 말뚝 (오른쪽)에서 첫 번째 말뚝 (왼쪽)까지의 경로를 따라 가면 파일 제거를 얻을 수 있습니다. 중요한 것은이 파일의 길이는 파일 수와 같습니다. 따라서 사용 된 파일 수는 최소입니다.

마지막으로 책을 겹치지 않고 최소 개수의 말뚝으로 구성 했으므로 최소 겹침 수를 가진 하나의 말뚝을 얻기 위해 서로 쌓아 놓을 수 있습니다.

* 이 유용한 의견 은 몇 가지 사항을 설명합니다


3
해명적인 증거를 위해 +1하고 토론에 연결하십시오. xnor et al.
COTO

딜 워스의 정리는 전체 증거를 다루지 않으며, 가장 적은 수의 말뚝이 가장 큰 크기의 안티 파일과 같다는 사실을 분명히해야합니다.
xnor
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.