일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 인텔리제이테스트클래스생성
- 프로그래머스
- 프로그래머스N으로표현
- 자바
- 백준피보나치수
- 프로그래머스자바
- 프로그래머스전화번호목록
- 백준피보나치
- 백준팩토리얼자바
- 프로그래머스해쉬
- 인텔리제이단축키
- intelliJ단축키
- 테스트클래스생성단축키
- 알고리즘
- 코딩연습
- 백준
- 완전탐색
- java
- C++
- 프로그래머스JAVA
- 전화번호목록자바
- dfs
- 백준하노이탑
- 백준벌집
- 카카오코딩연습
- springboot
- 스프링부트와 AWS로혼자구현하는웹서비스
- 백준팩토리얼
- 프로그래머스완주하지못한선수
- 알고리즘공부
- Today
- Total
말랑말랑
[백준] 11729번 하노이탑 본문
[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);
}
}
}
결과
추후에 옮기는 과정을 그림으로 추가해야겠다!
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 10870번 피보나치 수 (0) | 2021.04.21 |
---|---|
[백준] 10872번 팩토리얼 (0) | 2021.04.21 |
[백준] 2292번 벌집 (0) | 2021.03.06 |
[백준] 1712번 손익분기점 구하기 (0) | 2021.03.06 |