[42] push_swap 최적화

Arat5724·2023년 2월 10일
0

stack

push_swap에서는 stack aa와 stack bb, 2개의 stack을 사용한다.

여기서는 stack aa와 stack bb를 합친 자료구조를 stacks이라고 표현할 것이다.

또한 aa에 1, 2, 3, 4, 5가 들어있고 bb에 6, 7, 8가 들어있는 stacks TT를 아래와 같이 표현할 것이다.

T=[[12345][678]]T= \begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} 6 \\ 7 \\ 8 \end{bmatrix} \end{bmatrix}

정렬된 stacks

어떤 stacks TT이 정렬되어있다는 것은 TT의 모든 요소(숫자)가 stack aa에 오름차순으로 정렬되어있다는 것을 뜻한다.

동작(operation)

push_swap에서는 stacks의 요소(숫자)들의 위치 바꾸는 것을 '동작(operation)'이라고 한다.

push_swap에는 다음과 같은 11개의 동작(operation)들이 주어진다.

sasbsspapbrarbrrrrarrbrrrsa\quad sb\quad ss\quad pa\quad pb\quad ra\quad rb\quad rr\quad rra\quad rrb\quad rrr

ex) sa([[12345][]])=[[21345][]]sa( \begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix} ) = \begin{bmatrix} \begin{bmatrix} 2 \\ 1 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}

뿐만 아니라[[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}[[251][43]]\begin{bmatrix} \begin{bmatrix} 2 \\ 5 \\ 1 \end{bmatrix} \begin{bmatrix} 4 \\ 3 \end{bmatrix} \end{bmatrix}로 바꾸는 동작도 있을 수 있다.

이제 동작의 특성을 설명한 건데, 동작의 특성은 함수의 특성과 유사하므로, 간략하게만 설명한다.

역동작(Inverse operation)

A(T)=UA(T) = U일 때 AA의 역동작은 A1A^{-1}로 표기하고 A1(U)=TA^{-1}(U) = T인 동작이다.

ex) rb1=rrbrb^{-1}=rrb, sa1=sasa^{-1}=sa, pa1=pbpa^{-1}=pb

papa, pbpb의 역동작이 존재하기 위해서는, 정의역과 공역을 줄여야 한다.

동작의 합성

AABB를 합성한 동작 CCAABB의 합성 동작이라고 한다.

여기서는 편의를 위해 동작의 합성을 함수와 같이 ABA\,∘\,B같이 표현하는 것보다는
A×BA×B 혹은 ABA\,B와 같이 나열하는 것으로 표현할 것이다.

모든 동작은 항상 주어진 11개의 동작(sa  sb  ...  rrrsa\; sb\; ...\; rrr) 중 하나이거나 주어진 동작들의 합성 동작이다.
(경우에 의한 증명과 수학적 귀납법으로 증명 가능하지만 생략한다.)

또한 어떤 동작 AA가 되는 주어진 동작의 경우는 유일하지 않을 수 있고, 주어진 동작들을 합성하는 경우는 무수히 많다.

ex) T=[[12][]]T= \begin{bmatrix} \begin{bmatrix} 1 \\ 2 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}일 때, (rra)(T)=(ra)(T)=(sa)(T)=[[21][]](rra)(T) = (ra)(T) = (sa)(T) = \begin{bmatrix} \begin{bmatrix} 2 \\ 1 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}

ex) T=[[12345][678]]T= \begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} 6 \\ 7 \\ 8 \end{bmatrix} \end{bmatrix}일 때, (rb×pb×rrb)(T)=(pb×sb)(T)=[[2345][6178]](rb×pb×rrb)(T) = (pb×sb)(T) = \begin{bmatrix} \begin{bmatrix} 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} 6 \\ 1 \\ 7 \\ 8 \end{bmatrix} \end{bmatrix}

합성 동작의 역동작

(A×B)1=B1×A1(A×B)^{-1}=B^{-1}×A^{-1} (합성 함수의 역함수를 생각해보자.)

교환 법칙

모든 동작 AABB에 관해 A×BB×AA × B \not= B × A가 항상 성립하지는 않는다.

ex) T=[[12345][678]]T= \begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} 6 \\ 7 \\ 8 \end{bmatrix} \end{bmatrix}일 때, (pb×sa)(T)=[[3245][1678]](sa×pb)(T)=[[1345][2678]](pb×sa)(T) = \begin{bmatrix} \begin{bmatrix} 3 \\ 2 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} 1 \\ 6 \\ 7 \\ 8 \end{bmatrix} \end{bmatrix} \not= (sa×pb)(T) = \begin{bmatrix} \begin{bmatrix} 1 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} 2 \\ 6 \\ 7 \\ 8 \end{bmatrix} \end{bmatrix}

물론 성립할 때도 있다.

ex) T=[[12345][678]]T= \begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} 6 \\ 7 \\ 8 \end{bmatrix} \end{bmatrix}일 때, (ra×rb)(T)=(rb×ra)(T)=[[23451][786]](ra×rb)(T) = (rb×ra)(T) = \begin{bmatrix} \begin{bmatrix} 2 \\ 3 \\ 4 \\ 5 \\ 1 \end{bmatrix} \begin{bmatrix} 7 \\ 8 \\ 6 \end{bmatrix} \end{bmatrix}

항등 동작 II

어떤 동작 AA과 모든 stacks TT에 관해, A(T)=TA(T) = T가 성립할 때,

A=IA = I

라고 하고 II는 항등 동작이라고 한다.

역동작을 사용해 경우의 수를 늘려보자.

역동작을 사용해 어떤 알고리즘을 쓰든 경우의 수를 2배로 늘릴 수 있는 방법이다.

SS를 정렬된 stacks [[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}[[15234][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 5 \\ 2 \\ 3 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}로 만드는 동작이라고 하자.

그렇다면 동작 SS의 역동작은 항상 존재하고,
SS의 역동작 S1S^{-1}[[15234][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 5 \\ 2 \\ 3 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}를 정렬된 stacks [[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}로 만드는 동작이고

정렬된 stacks [[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}[[13452][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 3 \\ 4 \\ 5 \\ 2 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}로 만드는 동작으로도 볼 수 있다.

더 풀어서 설명하자면 aa만 봤을 때

n 1 2 3 4 5
m 1 5 2 3 4

SS는 표에서 n 자리에 m이 오게 하는 동작이고, S1S^{-1}는 m자리에 n이 오게 하는 동작이다.
n과 m의 관계를 해치지 않고, m을 오름차순으로 정렬하면 이런 표가 나온다.

n 1 3 4 5 2
m 1 2 3 4 5

따라서 S1S^{-1}[[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}[[25431][]]\begin{bmatrix} \begin{bmatrix} 2 \\ 5 \\ 4 \\ 3 \\ 1 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}로 만드는 동작인 것이다.

우리는 알고리즘을 통해 S×P1×P2×...×Pn=IS×P1×P2×...×Pn=I를 만족하는 P1,P2,...,PnP1,P2,...,Pn를 찾을 수 있다.

또한 S1×Q1×Q2×...×Qm=IS^{-1}×Q1×Q2×...×Qm=I를 만족하는 Q1,Q2,...,QmQ1,Q2,...,Qm도 찾을 수 있다.
(Pk(0<kn)Pk(0<k≤n)Qk(0<km)Qk(0<k≤m)는 주어진 동작 중 하나이다.)

P1×P2×...×Pn=S1P1×P2×...×Pn=S^{-1}, Q1×Q2×...×Qm=SQ1×Q2×...×Qm=S가 만족하므로 P1×P2×...×Pn=(Q1×Q2×...×Qm)1=Qm1×Qm11×...×Q11P1×P2×...×Pn=(Q1×Q2×...×Qm)^{-1}=Qm^{-1}×Qm-1^{-1}×...×Q1^{-1}이다.

따라서 P1,P2,...,PnP1,P2,...,PnQ1,Q2,...,QmQ1,Q2,...,Qm를 구하고 m<nm<n이라면 Qm1Qm^{-1}, Qm11Qm-1^{-1}, ......, Q11Q1^{-1}을 출력하면 될 것이다.

예를 들어, 정렬된 stacks에 동작 SS를 적용한 [[15234][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 5 \\ 2 \\ 3 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}를 삽입 정렬로 정렬해보자.
[[15234][]]ra×ra×pb×rra×pa×rra=[[12534][]]rra×rra×pb×rra×pa×rra×rra=[[12354][]]rra×pb×rra×pa×ra×ra=[[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 5 \\ 2 \\ 3 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}→ra×ra×pb×rra×pa×rra=\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 5 \\ 3 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}→rra×rra×pb×rra×pa×rra×rra=\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 5 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}→rra×pb×rra×pa×ra×ra=\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}
총 20번으로 정렬되었다. 최적화를 잘 하면 ra×sa×ra×sa×ra×sa×ra×rara×sa×ra×sa×ra×sa×ra×ra 8번으로 정렬 가능하다.

이번엔 정렬된 stacks에 동작 S1S^{-1}를 적용한 [[13452][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 3 \\ 4 \\ 5 \\ 2 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}를 삽입 정렬로 정렬해보자.
[[13452][]]rra×pb×ra×pa×rra=[[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 3 \\ 4 \\ 5 \\ 2 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}→rra×pb×ra×pa×rra=\begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}
총 5번으로 정렬되었다. 최적화를 잘 하면 rra×sarra×sa 단 2번으로 정렬 가능하다.

이것은 P1=raP1 = ra, P2=saP2 = sa, ..., P8=raP8 = ra이고 Q1=rraQ1 = rra, Q2=saQ2 = sa인 상황이다.
아까 Q21×Q11=S1Q2^{-1}×Q1^{-1}=S^{-1}이라고 했으니, S×Q21×Q11=IS×Q2^{-1}×Q1^{-1}=I인지 살펴보자.
Q21=sa1=saQ2^{-1}=sa^{-1}=sa
Q11=rra1=raQ1^{-1}=rra^{-1}=ra이므로
[[15234][]]sa=[[51234][]]ra=[[12345][]]\begin{bmatrix} \begin{bmatrix} 1 \\ 5 \\ 2 \\ 3 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}→sa= \begin{bmatrix} \begin{bmatrix} 5 \\ 1 \\ 2 \\ 3 \\ 4 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}→ra= \begin{bmatrix} \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix} \begin{bmatrix} \end{bmatrix} \end{bmatrix}

당연하게도 놀랍게도 정렬되는 것을 볼 수 있다.
ra×sa×ra×sa×ra×sa×ra×rara×sa×ra×sa×ra×sa×ra×ra이 아닌 sa×rasa×ra를 출력해도 된다는 것이다.

ra×sa×ra×sa×ra×sa×ra×rara×sa×ra×sa×ra×sa×ra×ra을 최적화해서 sa×rasa×ra가 될 수도 있기는 하지만, 주어진 동작을 많이 합성하는 경우에는 그럴 가능성이 매우 적다. 위에서 말했듯 어떤 동작 AA가 되는 주어진 동작들을 합성하는 경우는 무수히 많기 때문이다.
편차가 적은 알고리즘일수록 효과가 적다. (알고리즘의 시간 복잡도를 big-Theta로 나타낼 수 있을 때) ex) merge sort, qucik sort

만약 정렬하는 nn단계의 각 동작들이 역동작이 존재한다면 경우의 수를 최대 2n2^{n}배로 늘릴 수 있다.
혹은 각 단계에서 더 적은 동작을 선택한다고 해보자.
S×AS×A 혹은 S1×BS^{-1}×B로 1단계를 완성한다.
BB보다 AA가 동작이 더 적다면, AA를 선택하고,
S×A×CS×A×C 혹은 A1×S1×DA^{-1}×S^{-1}×D로 2단계를 완성한다.
CC보다 DD가 동작이 더 적다면, DD를 선택하고,
A1×S1×D×EA^{-1}×S^{-1}×D×E 혹은 D1×S×A×FD^{-1}×S×A×F로 3단계를 완성한다.
FF보다 EE가 동작이 더 적다면, EE를 선택하고, 정렬이 끝났다고 해보자.
그렇다면 A1×S1×D×E=IA^{-1}×S^{-1}×D×E=I이다.
양변에 역을 취하면
(A1×S1×D×E)1=I1(A^{-1}×S^{-1}×D×E)^{-1}=I^{-1}
합성 동작의 역동작의 성질로
E1×D1×S×A=IE^{-1}×D^{-1}×S×A=I
양변에 동작을 합성
D×E×(E1×D1×S×A)×E1×D1=D×E×I×E1×D1D×E×(E^{-1}×D^{-1}×S×A)×E^{-1}×D^{-1}=D×E×I×E^{-1}×D^{-1}
역함수의 정의에 의해
S×A×E1×D1=IS×A×E^{-1}×D^{-1}=I
정렬된 stacks에 SS가 적용된 상태에서, A×E1×D1A×E^{-1}×D^{-1}을 적용하면 정렬이 된다는 뜻이다.

다른 최적화 기법들은 다음 시간에 ^^...

profile
Jeongble

0개의 댓글