분할 정복이란?
한 번에 해결하기 어려운 문제를 해결 가능한 단위로 나누고,
작은 문제들을 해결한 후 합쳐서 큰 문제를 해결하는 방법
아래 하노이 탑 예제를 보고 이를 적용해보자.
* 원판의 개수가 2개, 3개라고 생각하고 그림을 그리면 이해가 빠를 것이다.
결국에는 같은 루트로 원판들이 옮겨지는 것이라고 생각하면 된다.
* String 대신에 StringBuilder를 사용해서 탐색 속도를 빠르게 했다.
단순한 알고리즘에서는 큰 차이가 없지만 복잡해질수록 차이가 나므로 StringBuilder 사용에 익숙해지자.
import java.util.Scanner;
public class Ex4 {
static StringBuilder sb = new StringBuilder(); // 이동 순서가 담길 배열
static int cnt = 0; // 이동 횟수
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
hanoi(n, 1, 2, 3); // 막대기 세 개를 순서대로 1, 2, 3으로 지정해줌
System.out.println(cnt);
System.out.println(sb);
}
// 원판의 개수(n), 출발지(1), 경유지(2), 목적지(3)
public static void hanoi(int n, int start, int mid, int to) {
cnt++; // 이동 횟수 증가
// 이동할 원반의 수가 1개라면
if(n == 1) {
sb.append(start + " " + to + "\n"); // 바로 1번에서 3번으로 이동해라.
return;
}
// 이동할 원판의 수가 1개가 아닐 때
// 첫째: n-1개를 1번에서 2번으로 이동 (그래야 1번 맨 아래에 있는 원판이 3번으로 가지)
// 과정: 1번의 원판들을 3번 막대기를 이용해서 2번으로 옮기자. 그래야 3번이 비니까.
hanoi(n-1, start, to, mid); // 따라서, 1->3->2 순서가 됨
// 둘째: 1번에 남아있는 제일 큰 원판을 1번에서 3번으로 이동
sb.append(start + " " + to + "\n");
// 셋째: n-1개를 2번에서 3번으로 이동 (이제 얘네들도 목적지로 보내주자)
// 과정: 2번에 남아있는 원판들을 1번을 이용해서 3번으로 옮겨주자.
hanoi(n-1, mid, start, to); // 따라서, 2->1->3 순서가 됨
}
}
완벽하게 이해가 된 문제가 아니라 재귀에 대해 좀 더 익숙해지고 문제를 다시 풀어보자!
'ALGORITHM' 카테고리의 다른 글
[백준 2750 / 2751 Java] 수 정렬하기 - 선택 정렬 / Arrays / Collections (0) | 2021.01.03 |
---|---|
[백준 2331 Java] 분해합 / 각 자리의 합 구하기 (0) | 2020.12.31 |
재귀 함수 (0) | 2020.12.30 |
[백준 2908 Java] 문자열 뒤집기 - StringBuffer / StringBuilder (0) | 2020.12.29 |
[백준 10809 Java] indexOf() (0) | 2020.12.28 |