코딩테스트/백준 단계별

[백준 9단계] 11729 하노이의 탑 이동 순서

scone 2022. 5. 16. 02:14

🥕 [ 백준 11729 ] 하노이의 탑 이동 순서

문제 링크

url : https://www.acmicpc.net/problem/11729

 

11729번: 하노이 탑 이동 순서

세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로

www.acmicpc.net

 

🍒 문제 분석

유명한 하노이의 탑 이동 문제 입니다.

작은 원판 위에는 큰 원판을 올릴 수 없고, 한번에 하나의 원판만을 옮길 수 있으며,

최적의 동선으로 1에서 3으로 탑을 옮겨야만 하죠.

🥑 코드

def moveDisc(cnt, from_bar, to_bar, via_bar):
    global anslist
    if cnt == 1:
        anslist.append([from_bar,to_bar])
    else:
        moveDisc(cnt-1,from_bar,via_bar,to_bar)
        moveDisc(1,from_bar,to_bar,via_bar)
        moveDisc(cnt-1,via_bar,to_bar,from_bar)

cnt = int(input())
anslist = []
moveDisc(cnt,1,3,2)
print(len(anslist))
for li in anslist:
    print(f'{li[0]} {li[1]}')

 

🍓 내 해결 과정

그림을 그렸다.

 

moveDisc(cnt-1,from_bar,via_bar,to_bar)
moveDisc(1,from_bar,to_bar,via_bar)
moveDisc(cnt-1,via_bar,to_bar,from_bar)

1. 1번(from)에서 원판 하나 빼고 나머지 것들을 2번(경유지)으로 옮긴다. ; 함수 호출

2. 1번(from)에 남은 원판을 3번(to) 로 옮긴다. ; 함수 호출

3. 2번(via)에 있는 원판들을 3번(to)으로 옮긴다. ; 함수 호출

 

이처럼 하나의 함수 안에 재귀 호출 3번이 이루어진다.

다만 원판이 1개 일때는 더 이상 재귀 호출을 하지 않으므로 값을 반환해주거나 또는 실행하고자 하는 바를 써야 한다는 것에 유의 한다.

 

🌽 다른 사람 코드

cache = {}

def h(f, v, t, n):
    if n == 1:
        return f'{f} {t}\n'      # f-string
    if (f, v, t, n) in cache:
        return cache[(f, v, t, n)]
    else:
        cur = [h(f, t, v, n - 1), f'{f} {t}\n', h(v, f, t, n - 1)]
        cache[(f, v, t, n)] = ''.join(cur)
        return cache[(f, v, t, n)]


N = int(input())
sum = 1
for i in range(N-1):
    sum = sum*2 + 1
print(sum)
print(h(1, 2, 3, N))

1. 처음에는 재귀를 통해 경로를 딕셔너리에 저장한다.

2. 만약 동일한 경로를 불러올 경우, 딕셔너리에 저장되어 있는 경로일 경우 고대로 불러온다.

3. 재귀를 몇번 호출하느냐는 주어진 cnt에 대한 규칙성을 이용해 계산하여 프린트했다.

 

🍉 깨달은 점 및 정리

1. 하노이 탑 이동 재귀함수를 쓰는 법을 알았다.

2. 딕셔너리 활용은 연습을 좀 더 해서 능숙해졌을 때야 가능하겠다.