[백준 11729] 하노이 탑 이동 순서 (자바)
백준 11729번 하노이 탑 이동 순서 (자바)
출처
11729번: 하노이 탑 이동 순서
세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로
www.acmicpc.net
문제
세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로 옮기려 한다.
- 한 번에 한 개의 원판만을 다른 탑으로 옮길 수 있다.
- 쌓아 놓은 원판은 항상 위의 것이 아래의 것보다 작아야 한다.
이 작업을 수행하는데 필요한 이동 순서를 출력하는 프로그램을 작성하라. 단, 이동 횟수는 최소가 되어야 한다.
아래 그림은 원판이 5개인 경우의 예시이다.
입력
첫째 줄에 첫 번째 장대에 쌓인 원판의 개수 N (1 ≤ N ≤ 20)이 주어진다.
출력
첫째 줄에 옮긴 횟수 K를 출력한다.
두 번째 줄부터 수행 과정을 출력한다. 두 번째 줄부터 K개의 줄에 걸쳐 두 정수 A B를 빈칸을 사이에 두고 출력하는데, 이는 A번째 탑의 가장 위에 있는 원판을 B번째 탑의 가장 위로 옮긴다는 뜻이다.
제한
- 1 ≤ N, M ≤ 10
- 1 ≤ K ≤ min(4, N×M)
- 격자판에 들어있는 수는 -10,000보다 크거나 같고, 10,000보다 작거나 같은 정수이다.
- 항상 K개의 칸을 선택할 수 있는 경우만 입력으로 주어진다.
입출력 예
풀이 방법
1. 하노이의 탑 원리를 이해하자.
ko.wikipedia.org/wiki/%ED%95%98%EB%85%B8%EC%9D%B4%EC%9D%98_%ED%83%91
- 2개(1, 2번째)의 돌을 A에서 B로 옮긴다.
- 3번째 돌을 A에서 C로 옮긴다.
- 1. 에서 빼놓았던 돌을 B에서 C로 옮긴다.
출처: https://editor752.tistory.com/132 [CF::LF]
2. 전체 경우의 수는 2^n-1이다.
3. A -> B로 옮기는 재귀와 B -> C 재귀를 따로 선언한다.
4. 옮길 개수가 1개 남았을 때 출력한다.
* 추가적으로 이문제는 StringBuilder를 사용하지 않으면 시간 초과가 나는데 이유는 아래의 블로그를 참고해주시기 바란다.
StringBuilder vs System.out.println :: 마이구미
이번 글의 제목은 "StringBuilder vs System.out.println" 이다. 글의 목적은 알고리즘 문제들의 시간을 줄이는 것이다. 그렇다면 어떻게 줄일 수 있는지 천천히 살펴보자. 대부분 알고 있듯이 System.out.print
mygumi.tistory.com
내 코드
package reflection;
import java.util.Scanner;
public class HanoiTop {
private static StringBuilder sb = new StringBuilder();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
//하노이의 탑 전체 경우의 수 - 2^n - 1
sb.append((int)Math.pow(2, n)-1 + "\n");
cycle(n, 1, 2, 3);
System.out.println(sb);
}
private static void cycle(int n, int one, int two, int three) {
if (n == 1) {
sb.append(one + " " + three + "\n");
} else {
//하노이의 탑 진행과정
//n-1번째까지의 돌을 A에서 B로 옮긴다.
//n번째 돌을 A에서 C로 옮긴다.
//1에서 빼놓았던 n-1번째까지의 돌을 B에서 C로 옮긴다.
cycle(n-1, one, three, two);
sb.append(one + " " + three + "\n");
cycle(n-1, two, one, three);
}
}
}
고려할 점
1. 재귀를 사용할 것
2. 1 -> 3으로 옮기는 것이기 때문에 1번에 있는 원소와 3번에 있는 원소를 출력할 것
3. 재귀 진행 시마다 개수-1 해줄 것
4. StringBuilder 사용해야 시간 초과가 나지 않는다.