알고리즘

[알고리즘] 하노이 탑 이동순서(백준 11729/파이썬)

Unknown200 2021. 3. 14. 23:03

필요한 개념:재귀함수

 

재귀함수란?

재귀호출이라고도 불리며 함수 안에서 자신을 다시 호출하여 작업을 수행하는 방식의 함수입니다. 
반복문을 사용하는 코드는 재귀 함수를 통해 구현하는 것이 가능합니다.

재귀 함수를 작성할때는 함수 내에서 다시 자신을 호출 한 후 그 함수가 끝날 때까지 함수 이후의

명령문이 수행되지 않기 때문에 무한루프를 방지하기 위하여 원하는 값을 얻으면 종료하거나 들어가는 인자값이

계속 변하는등 '종료조건'을 꼭 포함하여야 합니다.
재귀 함수는 메모리를 많이 차지 하기 때문에 재귀 함수를 많이 사용하면 스택 메모리가 커지고
호출하는 횟수가 많아지므로 스택오버플로우가 발생할 수 있습니다.

 

[문제]

 

 

[문제해결방법]

하노이의 탑은 시작 기둥에서 도착 기둥으로 모든 원판을 옮기는 것이 목표입니다.

조건은 작은 원판 위에 큰 원판이 올라갈 수 없다고 합니다.

기둥이 출발기둥: A, 보조기둥: B, 도착기둥: C 3개가 있고 원판이 6개 있을때 

마지막 원판이 도착지인 c에 가려면 각 원판을 처음 움직일 때는 아래의 그림처럼 각 원판의 도착지가 정해집니다.

 

 

위에 그림처럼 원판을 이동할 때 처음에는

1원판: A -> B로 이동, 2원판: A ->C로 이동하고 3원판이 B기둥으로 이동하려는데

조건에 작은 원판 위에 큰 원반이 올라 갈 수 없으니 다시 1원판: B -> c로 이동하고 3원판: A -> B로 이동하게 됩니다.

 출발         도착

1원반 :   A     ->     B         

2원반 :   A     ->     C         

1원반 :   B      ->    C         

3원반 :   A     ->     B         

이런식으로 출발지와 도착지가 변경되는 코드를 짜면 됩니다.

출발지와 도착지가 계속 반복 되니까 이 부분을 재귀함수를 사용하면 됩니다.

 

[코드리뷰]

import sys

move =[]
#원판이 움직였을때 위치 값을 담아주기 위해서 리스트를 만듭니다.
          # 시작  도착
def hanoi(n, A, B, C):
       #     1  2  3
       # n=2 1  3  2
       # n=1 1  1  3
    if n==1:
        move.append([A,C])
        #원판이 한개 남았을때 움직인 값을 move에 저장합니다.
    else:
        hanoi(n-1,A,C,B)
        #n-1 = 2  1 3 2 
        #n-1 = 1  1 2 3 
        move.append([A,C])
        #움직인 값을 move에 저장합니다.
        hanoi(n-1,B,A,C)
        #그 다음 원판을 계산하기 위해 다시 하노이 함수를 호출합니다.
a=int(sys.stdin.readline())
#원판의 개수를 받는다
hanoi(a,1,2,3)
#하노이 함수를 호출한다
print(len(move))
#옮긴 횟수를 프린트하기 위해 move의 길이를 출력하여 줍니다.
print('\n'.join([' '.join(str(i) for i in row )for row in move]))
#move안에 있는 수(i, row)들을 문자열로 바꾸고 띄어쓰기를 넣고 줄을 바꿔 프린트 합니다.

 

[결과]

아래에 나오는 결과처럼 재귀 함수 호출을 많이 할수록 메모리 값이 커집니다.