알고리즘/백준

[백준 11729] 하노이 탑 이동 순서 (자바)

마데카솔라 2020. 10. 1. 00:18
반응형

백준 11729번 하노이 탑 이동 순서 (자바)

 

 

출처

www.acmicpc.net/problem/11729

 

11729번: 하노이 탑 이동 순서

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

www.acmicpc.net

 

 

 

 

문제

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

  1. 한 번에 한 개의 원판만을 다른 탑으로 옮길 수 있다.
  2. 쌓아 놓은 원판은 항상 위의 것이 아래의 것보다 작아야 한다.

이 작업을 수행하는데 필요한 이동 순서를 출력하는 프로그램을 작성하라. 단, 이동 횟수는 최소가 되어야 한다.

아래 그림은 원판이 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

 

 

풀이 방법

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를 사용하지 않으면 시간 초과가 나는데 이유는 아래의 블로그를 참고해주시기 바란다.

mygumi.tistory.com/83

 

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 사용해야 시간 초과가 나지 않는다.

 

 

반응형