하노이의 탑
문제 이해
하노이의 탑은 한 기둥에 쌓인 원판을 다른 기둥으로 모두 옮기는 퍼즐이다.
원판은 한 번에 하나만 옮길 수 있다.
각 기둥에서는 가장 위에 있는 원판만 꺼낼 수 있다.
큰 원판은 작은 원판 위에 올릴 수 없다.
원판 개수별 이동 과정
원판이 n개일 때 최소 이동 횟수는 2^n - 1이다.
A: 시작 기둥
B: 보조 기둥
C: 목표 기둥
원판 크기:
- 소 → 가장 작은 원판
- 중 → 작은 다음 크기
- 대 → 큰 원판
- 특 → 가장 큰 원판
원판 1개
- A -> C 소
- A: [ ] B: [ ] C: [소]
원판 2개
- A -> B 소
- A: [중] B: [소] C: [ ]
- A -> C 중
- A: [ ] B: [소] C: [중]
- B -> C 소
- A: [ ] B: [ ] C: [중,소]
원판 3개
- A -> C 소
- A: [대,중] B: [ ] C: [소]
- A -> B 중
- A: [대] B: [중] C: [소]
- C -> B 소
- A: [대] B: [중,소] C: [ ]
- A -> C 대
- A: [ ] B: [중,소] C: [대]
- B -> A 소
- A: [소] B: [중] C: [대]
- B -> C 중
- A: [소] B: [ ] C: [대,중]
- A -> C 소
- A: [ ] B: [ ] C: [대,중,소]
원판 4개
- A -> B 소
- A: [특,대,중] B: [소] C: [ ]
- A -> C 중
- A: [특,대] B: [소] C: [중]
- B -> C 소
- A: [특,대] B: [ ] C: [중,소]
- A -> B 대
- A: [특] B: [대] C: [중,소]
- C -> A 소
- A: [특,소] B: [대] C: [중]
- C -> B 중
- A: [특,소] B: [대,중] C: [ ]
- A -> B 소
- A: [특] B: [대,중,소] C: [ ]
- A -> C 특
- A: [ ] B: [대,중,소] C: [특]
- B -> C 소
- A: [소] B: [대,중] C: [특]
- B -> A 중
- A: [중] B: [대] C: [특,소]
- C -> A 소
- A: [중,소] B: [대] C: [특]
- B -> C 대
- A: [중,소] B: [ ] C: [특,대]
- A -> B 소
- A: [중] B: [소] C: [특,대]
- A -> C 중
- A: [ ] B: [소] C: [특,대,중]
- B -> C 소
- A: [ ] B: [ ] C: [특,대,중,소]
풀이
풀이 코드에서도 A는 시작 기둥, B는 보조 기둥, C는 목표 기둥으로 사용한다.
출력의 disk 1은 가장 작은 원판을 뜻한다.
숫자가 커질수록 더 큰 원판을 뜻하므로 원판이 3개라면 disk 3이 가장 큰 원판이다.
이동 과정 출력하기
#include <stdio.h>
void hanoi(int n, char from, char via, char to)
{
if (n == 0)
return;
hanoi(n - 1, from, to, via);
printf("disk %d: %c -> %c\n", n, from, to);
hanoi(n - 1, via, from, to);
}
int main(void)
{
int n = 3;
hanoi(n, 'A', 'B', 'C');
return 0;
}
이동 과정 저장하기
#include <stdio.h>
#include <stdlib.h>
typedef struct s_step
{
int disk;
char from;
char to;
} t_step;
void hanoi(int disk_count, char from, char via, char to, t_step steps[], int* step_index)
{
if (disk_count == 0)
return;
hanoi(disk_count - 1, from, to, via, steps, step_index);
steps[*step_index].disk = disk_count;
steps[*step_index].from = from;
steps[*step_index].to = to;
(*step_index)++;
hanoi(disk_count - 1, via, from, to, steps, step_index);
}
int main(void)
{
int disk_count = 3;
int step_count = (1 << disk_count) - 1;
int step_index = 0;
t_step* steps = malloc(sizeof(t_step) * step_count);
hanoi(disk_count, 'A', 'B', 'C', steps, &step_index);
for (int i = 0; i < step_count; i++)
printf("disk %d: %c -> %c\n", steps[i].disk, steps[i].from, steps[i].to);
free(steps);
return 0;
}