알고리즘/백준

[백준] 11729번 하노이탑

말랑말랑쓰 2021. 4. 21. 01:17

 

[21-04-20]

 

 

분명 배웠던 하노이탑이 새삼 새롭게 느껴졌다...

옛날 옛적 알고리즘 수업 시간에도 하노이탑의 풀이과정은 뭔가 이해가 잘 되지 않았었는데

아마 나는 재귀 자체에 약한가보다...^^^,,, 이번에도 역시,..,,ㅎㅎ

익숙하게 다룰 수 있도록 열공하자,,,^^,,,

 

 


 

문제

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

 

11729번: 하노이 탑 이동 순서

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

www.acmicpc.net

 

 

분석

문제 자체가 이동 횟수도 출력해야 하고 이동 과정도 출력해야 한다.

그럼 함수 어딘가에 출발지 > 목적지와 같은 출력문이 분명히 들어갈 것이다.

또한 무조건 큰 원반이 아래에 위치하고 작은 원반이 위에 있어야 한다. 

 

재귀는 어떤 구간이 반복되어 호출되는지와 기저사례를 찾아야 하기 때문에

직접 옮겨보며 다음과 같은 특징을 파악했다.

 

1. 맨 아래의 원반을 옮기기 위해서는 위에 쌓여있는 원반들이 모두 옮겨져야 한다.

  > 1번 꽂이에 4개의 원반이 꽂혀있으면, 맨 아래 원반을 제외한 3개(N-1)의 원반 이동이 일어나야 한다.

  > N개의 원반을 옮기는데 걸리는 횟수

    = 맨 아래 원반을 제외한 N-1개의 원반을 옮기는 횟수 + 1번(맨 아래 원반 옮기기) + N-1개의 원반을 목적지로 다시쌓는 횟수

  > 목적지에 다시 쌓는 것을 고려하면 N-1개의 원반 이동이 총 2번 일어나는 것을 알 수 있다. (옮겨놓기,다시 쌓기)

2. 원반 2개를 특정 위치로 옮기기 위해서는 다른 꽂이를 이용하여 교환해야 한다. (1개는 바로 이동시키면 됨)

   > 큰 원반이 작은 원반 위로 이동 할 수가 없기 때문에, 중간 지점을 두고 교환한다.

3. 원반 1개 이동이 출력과 같다.

  > 문제 자체가 이동을 출력하는 것이기 때문에 원반이 1개일 때는 다른 액션 없이 출력만 하면 된다.

 

 

알고리즘만 풀면 되지 않을까 싶었는데 왠걸 시간초과가뜬다.,..ㅎㅎㅎ...

찾아보니 System.out을 사용할 경우 시간이 많이 소요된다고 한다..☆

결국 출력문을 BufferWriter로 수정함

 

코드
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class Main {
	
	// 시간 때문에 System.out 쓰지 않고 Buffer로 사용
	static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	
	public static void main(String[] args) throws IOException {		
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		bw.write( (int)Math.pow(2, n) - 1 + "\n" );
		
		hanoi(n, 1, 3, 2);
		
		bw.close();
	}
	
	// n개의 원반이 목적지로 이동하기 위한 이동 내역을 출력하는 함수 
	public static void hanoi(int n, int source, int dest, int other) throws IOException {
		if(n == 1) {
			bw.write(source + " "+ dest + "\n" );	 // 원반이 1개면 바로 출력(옮기는 작업 필요X)
			return;
		} else {
			hanoi(n-1, source, other, dest);
			bw.write(source + " " + dest + "\n" );
			hanoi(n-1, other, dest, source);
		}
	}
	
}

 

 

 

결과

 

 

 


추후에 옮기는 과정을 그림으로 추가해야겠다!