- 세 개의 기둥에서 규칙을 지키면서 원판을 옮기는 재귀 알고리즘의 대표적인 문제이다.
- 한 번에 하나의 원판만 옮길 수 있다.
- 큰 원판이 작은 원판 위에 있어서는 안 된다.
[1] [] []
[] [] [1]
[1,2] [] []
[2] [1] []
[] [1] [2]
[] [] [1,2]
- 1을 빈칸에 옮기고 2를 옮긴후 다시 1을 올린다
[1,2,3] [] []
[2,3] [] [1]
[3] [2] [1]
[3] [1,2] []
[] [1,2] [3]
[1] [2] [3]
[1] [] [2,3]
[] [] [1,2,3]
- 2를 빈칸에 옮기고 3을 옮긴후 다시 2를 올린다
- 2를 옮길때마다 원판 2개에서의 행동이 필요하다
- A1 = 1
- A2 = 2 * A1 + 1
- A3 = 2 * A2 + 1`
...
- AN = 2*AN-1+1 번
- AN = 2N-1 + 2N-2 ... + 2 + 1
[1]
- 위 식에서 좌우에 2를 곱한다.
- 2AN = 2N + 2N-1 ... + 2
[2]
[2]
에서 [1]
을 뺀다.
- AN = 2N-1
- N개의 원판을 이동할때 필요한 시간 복잡도
- O(2N-1)
void hanoi(int n, int from, int by, int to){
if (n == 1){
System.out.printf("Move from %d to %d\n", from, to);
return;
}
hanoi(n - 1, from, to, by);
System.out.printf("Move from %d to %d\n", from, to);
hanoi(n - 1, by, from, to);
}
void hanoi(int n, int from, int by, int to)
{
if (n == 1)
{
cout << "Move from " << from << "to " << to << endl;
}
else
{
hanoi(n - 1, from, to, by);
cout << "Move from "<< from << "to "<< to << endl;
hanoi(n - 1, by, from, to);
}
}
def hanoi(n, from_pos, to_pos, aux_pos):
if n == 1:
print(from_pos, "->", to_pos)
return
hanoi(n - 1, from_pos, aux_pos, to_pos)
print(from_pos, "->", to_pos)
hanoi(n - 1, aux_pos, to_pos, from_pos)